Klasse in Klasse

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Campionissimo
User
Beiträge: 102
Registriert: Montag 28. März 2011, 07:50

Hallo und schon wieder ein kleines Problem.

Ich habe eine Klasse in der wieder eine Klasse ist und natürlich def.
z.B.
"
class haupt()
def ini
....
def auswertung
.....
class Thread
haupt.auswertung()
"

Warum kann ich nicht von der Klasse in die auswertung springen?
Weil dies dann nicht ging wollte ich variable von der ini() mit einbinden und natürlich auch wieder eine fehlermeldung, dass die variable nicht zu class thread gehört auch wenn ich vor der variablen den verweiss gab mit haupt.
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Hallo.

Aus deinen Sätzen wird man leider nicht ganz schlau was du vor hast. Ich empfehle dir daher zwei Sachen:

Beschreibe dein eigentlichen Problem, also was konkret möchtest du lösen. Vielleicht ist dein Ansatz schon nicht ganz korrekt und es gibt eine bessere Lösung für dein Problem.

Außerdem solltest du ein konkretes Beispiel schreiben (Code) und dies mit entsprechenden Kommentaren versehen was du erwartest. Du zeigst zwar etwas Code, aber der ist so allgemein, dass man damit nichts anfangen kann. Das Formu besitzt übrigens Tags für Python-Code, dann kann der Quelltext auch gelesen werden. Mit richtiger Einrückung, welche bei diesem Problem sicher nicht ganz unwichtig ist.

Sebastian
Das Leben ist wie ein Tennisball.
Campionissimo
User
Beiträge: 102
Registriert: Montag 28. März 2011, 07:50

Das ist mein Code verkürzt, weil es viele Zeilen sind nehm ich nur nen Teil heraus.

Code: Alles auswählen

class MyFrame(wx.Frame):

    def __init__(self,parent,id,title):
       
        wx.Frame.__init__(self, parent, id, title, pos=(0, 0), size=wx.DisplaySize(),style=wx.DEFAULT_FRAME_STYLE & ~ (wx.RESIZE_BORDER |                                wx.RESIZE_BOX | wx.MAXIMIZE_BOX))
    def ledauswertung(self):
        print "Hallo"    
class ThreadLED(threading.Thread):
        def __init__(self,queue3):
            self.queue3 = queue3
            self.Fehler=None
            threading.Thread.__init__(self)
            
        def run(self):
            print 2
           
            while True:
                
                fehler = self.queue3.get()
                if fehler != "":
                
                    #print "df56g4df56g456dfs4g564sdf56g56asdf56g54asdf564g456asdf4g456af56g456asdf4g564adf56s4g"
                    #print self.fehler
                    MyFrame.ledauswertung()
Also ich möchte mit dem Aufruf ledauswertung() in das Unterprogramm der Class MyFrame

hier die Fehlermeldung:

Code: Alles auswählen

Exception in thread Thread-4:
Traceback (most recent call last):
  File "C:\python25\lib\threading.py", line 488, in __bootstrap_inner
    self.run()
  File "C:\.....Modul_GUI.py", line 397, in run
    MyFrame.ledauswertung()
TypeError: unbound method ledauswertung() must be called with MyFrame instance as first argument (got nothing instead)
mutetella
User
Beiträge: 1695
Registriert: Donnerstag 5. März 2009, 17:10
Kontaktdaten:

Bin mir nicht sicher, worauf Du hinauswillst... Geht's Dir um sowas:

Code: Alles auswählen

class Main(object):
    MAIN = 'class Main'

    class Thread(object):
        THREAD = 'class Thread'
        def __init__(self):
            self.thread = 'Thread instance'
            self.from_main = Main.MAIN

    def __init__(self):
        self.main = 'Main instance'
        self.from_thread = Main.Thread.THREAD

Code: Alles auswählen

In [734]: m = Main()

In [735]: m.main
Out[735]: 'Main instance'

In [736]: m.from_thread
Out[736]: 'class Thread'
mutetella
Entspanne dich und wisse, dass es Zeit für alles gibt. (YogiTea Teebeutel Weisheit ;-) )
Benutzeravatar
sparrow
User
Beiträge: 4187
Registriert: Freitag 17. April 2009, 10:28

Du versuchst eine Funktion aus eine Klasse aufzurufen indem du sie über den Klassennamen absprichst.
Du musst aber ein Objekt (eine Instanz) von der Klasse erzeugen und darin die Methode aufrufen.
Wenn so etwas passiert sollte man sich daran erinnern, dass Klassen nicht als Code-Container mißbraucht werden sollten.

Code: Alles auswählen

>>> class house(object):
	def __init__(self, bewohner):
		self.bewohner = bewohner
	def klingeln(self):
		print "Du hast bei %s geklingelt" % (self.bewohner)

		
>>> house.klingeln()

Traceback (most recent call last):
  File "<pyshell#12>", line 1, in <module>
    house.klingeln()
TypeError: unbound method klingeln() must be called with house instance as first argument (got nothing instead)
>>> mein_haus = house('sparrow')
>>> mein_haus.klingeln()
Du hast bei sparrow geklingelt
Zuletzt geändert von sparrow am Dienstag 26. Juli 2011, 11:20, insgesamt 1-mal geändert.
frabron
User
Beiträge: 306
Registriert: Dienstag 31. März 2009, 14:36

Code: Alles auswählen

class A(object):
    def foo(self):
        print "Hallo"
        
a = A()
a.foo()        
A.foo()
HIer noch ein Beispiel zur Replikation deines Problems. Vielleicht hilft es ja deinem Verständnis von Klassen und Instanzen von Klassen :)
mutetella
User
Beiträge: 1695
Registriert: Donnerstag 5. März 2009, 17:10
Kontaktdaten:

Du kannst eine Methode nicht einfach wie eine Funktion behandeln.

Code: Alles auswählen

def test(foo):
    print foo

class Test(object):
    def __init__(self):
        pass

    def test(self, foo):
        print foo

Code: Alles auswählen

In [755]: test('bar')
bar

In [756]: Test.test('bar')
---------------------------------------------------------------------------
TypeError: unbound method test() must be called with Test instance as first argument (got str instance instead)

In [757]: t = Test()

In [758]: t.test('bar')
bar
Wenn die Instanz von 'MyFrame' z. B. 'frame' heißt, könntest Du 'frame.ledauswertung' an 'ThreadLED' übergeben und dort ausführen.

mutetella
Entspanne dich und wisse, dass es Zeit für alles gibt. (YogiTea Teebeutel Weisheit ;-) )
mutetella
User
Beiträge: 1695
Registriert: Donnerstag 5. März 2009, 17:10
Kontaktdaten:

Kleine Beispiel:

Code: Alles auswählen

class View(object):
    def __init__(self):
        pass

    def show(self, message):
        print message


class Blubb(object):
    def __init__(self, view):
        self.view = view

    def do_it(self):
        #make some stuff...
        self.view('Blubb is ready...')

Code: Alles auswählen

In [767]: v = View()

In [768]: b = Blubb(v.show)

In [769]: b.do_it()
Blubb is ready...
mutetella
Entspanne dich und wisse, dass es Zeit für alles gibt. (YogiTea Teebeutel Weisheit ;-) )
Campionissimo
User
Beiträge: 102
Registriert: Montag 28. März 2011, 07:50

Ich kapier was ihr meint, weiß aber nicht wie ich es übertragen soll. Ihr gebt es alle in ein Command Window ein. Ich hab leider eine IDE

Ich müsste ausserhalb der klasse sagen das b = MyFrame ist. Aber dann wird es wieder nicht akzeptiert.
Ich bin zu blöd für diese Welt ;)
mutetella
User
Beiträge: 1695
Registriert: Donnerstag 5. März 2009, 17:10
Kontaktdaten:

Ich nehme mal an, Du arbeitest unter Windows. Wenn Du dort in die Eingabeaufforderung wechselst und 'python'XX (für 'XX' gibst Du die bei Dir installierte Pythonversion, z. B. 26 für 2.6 ein) eingibst, öffnet sich dieses 'Command Window', auch Pythonshell genannt...
Unter Linux machst Du selbiges im Terminal, allerdings ohne 'XX'...

Dort gibst Du dann einfach mal unsere Beispiele ein und kannst damit experimentieren...

mutetella
Entspanne dich und wisse, dass es Zeit für alles gibt. (YogiTea Teebeutel Weisheit ;-) )
Campionissimo
User
Beiträge: 102
Registriert: Montag 28. März 2011, 07:50

Ja das weiss ich, dass ist aber nicht mein Problem.
Ich kann die Klasse einen Namen zuweisen usw.
das Problem ist ich bekomme in der Klasse Thread einen Wert von einer anderen Thread. Dann muss ich diesen Wert an ein Unterprogramm von der Klasse MyFrame übergeben.

Code: Alles auswählen

class MyApp(wx.App):
    def OnInit(self):
        frame = MyFrame(None,wx.ID_ANY,"TestOberflaeche")
        frame.Show(True)
        return True
ich habe das schon gemacht, dass es frame heisst, aber in der Klasse selbst wird frame natürlich nicht erkannt
Benutzeravatar
sparrow
User
Beiträge: 4187
Registriert: Freitag 17. April 2009, 10:28

Du kannst die Instanz einer Klasse mit self übergeben.

Code: Alles auswählen

>>> class House(object):
	def __init__(self, name):
		self.name = name
		self.doghouse = House.Doghouse(self) 
	def klingeln(self):
		print "Du hast bei %s geklingekt" % (self.name)
	class Doghouse(object):
		def __init__(self, owner):
			self.owner = owner
		def beim_besitzer_klingeln(self):
			self.owner.klingeln()

			
>>> my_house = House('sparrow')
>>> my_house.klingeln()
Du hast bei sparrow geklingekt
>>> my_house.doghouse.beim_besitzer_klingeln()
Du hast bei sparrow geklingekt
Aber: was du da tust sieht sehr chaotisch aus. Du vermischt Anwendungslogik und GUI offensichtlich sehr stark. Das ist nicht gut und bereitet hinterher Schmerzen.
BlackJack

@Campionissimo: Ich würde das Konzept eine Klasse als Attribut einer Klasse zu definieren in Python auch in Frage stellen. So etwas macht man in Python nicht. Es bringt im Grunde keine Vorteile. Was versprichst Du Dir denn davon? Die Exemplare wissen nichts voneinander. Es gibt semantisch keine inneren Klassen wie zum Beispiel bei Java.
mutetella
User
Beiträge: 1695
Registriert: Donnerstag 5. März 2009, 17:10
Kontaktdaten:

Campionissimo hat geschrieben:ich habe das schon gemacht, dass es frame heisst, aber in der Klasse selbst wird frame natürlich nicht erkannt
In der Klasse selbst wird 'frame' schon erkannt, nur heißt es dort dann 'self'.

Code: Alles auswählen

class Test(object):
    def __init__(self):
        self.attribute = 'bla'

    def show_attribute(self):
        print self.attribute
Ausgehend davon greifst Du von außen über 'instancename.attribute' auf 'bla' zu, innerhalb der Klasse über 'self.attribute':

Code: Alles auswählen

>>> t = Test()
>>> t.attribute
'bla'
>>> t.show_attribute()
'bla'
>>> getattr(t, 'attribute')
'bla'
Campionissimo hat geschrieben: ich bekomme in der Klasse Thread einen Wert von einer anderen Thread. Dann muss ich diesen Wert an ein Unterprogramm von der Klasse MyFrame übergeben.
Klassen besitzen keine Programme sondern Methoden. Und an diese kannst Du Werte übergeben.
Wenn Du von 'Thread' einen Wert an 'MyFrame' übergeben möchtest, brauchst Du in 'Thread' einen Zugriff auf eine 'MyFrame'-Instanz:

Code: Alles auswählen

class Frame(object):
    def __init__(self):
        self.value = None

    def set_value(self, value):
        self.value = value

class Thread(object):
    def __init__(self, frame_instance):
        self.frame_instance = frame_instance

    def apply_value2frame_instance(self, value):
        self.frame_instance.set_value(value)

Code: Alles auswählen

>>> frame = Frame()
>>> thread = Thread(frame)
>>> thread.apply_value2frame_instance('getted from thread')
>>> frame.value
'getted from thread'
>>> thread.frame_instance.value
'getted from thread'
>>> thread.value
AttributeError: 'Thread' object has no attribute 'value'
An dieser Steller empfehle ich Dir auch, das Python-Tutorial zu Namensräume und Klassen durchzulesen und etwas damit zu spielen...

mutetella
Entspanne dich und wisse, dass es Zeit für alles gibt. (YogiTea Teebeutel Weisheit ;-) )
Campionissimo
User
Beiträge: 102
Registriert: Montag 28. März 2011, 07:50

Danke für deine ausfürhliche Antwort.
Hab das ganze über eine queue gemacht und es hat funktioniert. Muss jetzt nach meinen neuesten Informationen von dir das ganze mal testen.
Vielen Vielen Dank.

Auf ein Problem bin ich jetzt mit den queue gestoßen.
Da du dich ja super auskennst könntest diese vielleicht auch beantworten!
Kann ich in einem Programm das mehrere Threads hat mehrere queue benutzen ?
d.h. queue = Queue.Queue()
queue1 = Queue.Queue()
queue2 = Queue.Queue()
queue3 = Queue.Queue()
? Oder stören sich die Teile .

Wenn man nur eine benutzen kan z.B die queue = Queue.Queue()
kann man hierzu auch mehrere queue.put(blabla) benutzen.
Möchte es nur wissen, bevor ich mein Programm wieder umstelle und du es wahrscheinlich auf anhieb weißt.
Mit den Fragen die ich stelle weiß ich jetzt schon einiges mehr.
Nochmal vielen Dank. Man lernt immer mehr.

Schönene Abend noch
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Hallo.

Wie kommst du darauf, das man nur eine Instanz von `Queue` benutzen können sollte? Du kannst davon beliebig viele erzeugen.

Sebastian
Das Leben ist wie ein Tennisball.
Campionissimo
User
Beiträge: 102
Registriert: Montag 28. März 2011, 07:50

Ich habe diese queue:

queue = Queue.Queue()
queue1 = Queue.Queue()
queue2 = Queue.Queue()
queue3 = Queue.Queue()

Mit der queue hat noch alles funktioniert!
Als ich die anderen hinzugefügt habe ging es nicht mehr.
Sprich ers wird was in die queue Übergeben (einmal) und dann kann nicht mehr in die queue übergeben werden.
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Dann hast du an einer anderen Stelle einen Fehler gemacht. Ohne den entsprechenden Code, oder am besten ein lauffähiges Minimalbeispiel, kann man natürlich nicht sagen wo der Fehler liegt. Ich würde mal darauf tippen, dass die die Queues bei dir gegenseitig blockieren.
Das Leben ist wie ein Tennisball.
Benutzeravatar
pillmuncher
User
Beiträge: 1484
Registriert: Samstag 21. März 2009, 22:59
Wohnort: Pfaffenwinkel

@Campionissimo: Was meinst du mit "kann nicht mehr in die queue übergeben werden"? Bleibt es hängen? Fliegt eine Exception? Oder ist einfach das Ergebnis nicht das, was du erwartest?
In specifications, Murphy's Law supersedes Ohm's.
Campionissimo
User
Beiträge: 102
Registriert: Montag 28. März 2011, 07:50

@EyDu
Ich glaube auch das sich die queue blockieren. Werde Sie jetzt nacheinander einsetzen und schauen wo das problem ist.
@pillmuncher
Ich bekomme einen Wert aus der queue und sonst keinen obwohl ich die ganze Zeit was put(e) ;) Bekomm alsdo nach dem ersten Wert kein zweites Ergebnis.
Antworten