OOP Problem / Verständnisfrage bezüglich 'self'

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.
BlackJack

@Schwarzer Wolf: Ich hatte weiter oben ja schon gezeigt auf was sich dieses Problem reduzieren lässt. Du rufst dort eine Methode auf einer *Klasse* auf die nicht auf der *Klasse* `Theaterstueck` sondern einem *Exemplar* von `Theatherstueck` aufgerufen werden muss. Benenn vielleicht mal das Attribut `daten` sinnvoll und nicht so generisch, dann fällt Dir sicher auf warum die Zeile so keinen Sinn macht. Zerleg die Zeile in ihre Teilausdrücke und überlege was jeder davon für einen Wert hat. Und dann überprüfe Deine Vermutung mit `print()` und `type()` für jeden Teilausdruck, bist Du zu dem Punkt kommst, wo Deine Erwartung von der Wirklichkeit abweicht.
Benutzeravatar
Schwarzer Wolf
User
Beiträge: 56
Registriert: Donnerstag 5. Januar 2017, 05:24

BlackJack hat geschrieben:@Schwarzer Wolf: Ich hatte weiter oben ja schon gezeigt auf was sich dieses Problem reduzieren lässt. Du rufst dort eine Methode auf einer *Klasse* auf die nicht auf der *Klasse* `Theaterstueck` sondern einem *Exemplar* von `Theatherstueck` aufgerufen werden muss. Benenn vielleicht mal das Attribut `daten` sinnvoll und nicht so generisch, dann fällt Dir sicher auf warum die Zeile so keinen Sinn macht. Zerleg die Zeile in ihre Teilausdrücke und überlege was jeder davon für einen Wert hat. Und dann überprüfe Deine Vermutung mit `print()` und `type()` für jeden Teilausdruck, bist Du zu dem Punkt kommst, wo Deine Erwartung von der Wirklichkeit abweicht.
Danke, nun hab ich es vermutlich kapiert. Habe den kleinen Beitrag erst jetzt richtig begriffen und wohl vorher wieder vergessen bei all den Antworten..

Ich gebe als 'self' den Klassennamen an, in dem die Methode ist?bIch hatte das glaube ich vorher mal probiert, aber scheinbar war dann etwas anderes Falsch. Jetzt geht es. :D :D :D

Wünsche Dir einen angenehmen Tag.

@ all

Danke für die Zeit, die Ihr Euch genommen habt.
Wer in der Wildnis lebt, muss zum Wolf werden, oder als Schaf sterben.
(Syrisches Sprichwort)
Sirius3
User
Beiträge: 17750
Registriert: Sonntag 21. Oktober 2012, 17:20

@Schwarzer Wolf: aus Deiner Antwort kann ich jetzt nicht herauslesen, ob Du es tatsächlich verstanden hast. ›self‹ wird beim Aufruf nicht explizit angegeben, weil automatisch das Exemplar als Parameter ›self‹ genommen, auf dem man die Methode aufruft.
Benutzeravatar
Schwarzer Wolf
User
Beiträge: 56
Registriert: Donnerstag 5. Januar 2017, 05:24

Sirius3 hat geschrieben:@Schwarzer Wolf: aus Deiner Antwort kann ich jetzt nicht herauslesen, ob Du es tatsächlich verstanden hast. ›self‹ wird beim Aufruf nicht explizit angegeben, weil automatisch das Exemplar als Parameter ›self‹ genommen, auf dem man die Methode aufruft.
Du hattest recht. Der richtige Aufruf ist vermutlich:

Code: Alles auswählen

self.daten.neue_auffuehrung(auffuehrung)
Zumindest macht der Code nun in der Datei, was er soll. Ich weiß, dass 'self' in der Regel leer bleibt. Daher hat mich das auch so gewundert. Habe wohl meiner IDE zu sehr vertraut.
Wer in der Wildnis lebt, muss zum Wolf werden, oder als Schaf sterben.
(Syrisches Sprichwort)
__deets__
User
Beiträge: 14541
Registriert: Mittwoch 14. Oktober 2015, 14:29

Das klingt immer noch komisch. self bleibt nicht leer. Es zeigt stattdessen auf die Instanz des Objektes:

Code: Alles auswählen

class Klasse(object):
    def foo(self): print(id(self)) # 1234567
    
foo = Klasse()
print(id(foo)) # 1234567
foo.methode() # siehe oben
jerch
User
Beiträge: 1669
Registriert: Mittwoch 4. März 2009, 14:19

Dazu ergänzend:

Code: Alles auswählen

In [1]: class Test(object):
   ...:     def test1(self):
   ...:         print self
   ...:         

In [2]: def test_function(self):
   ...:     print self
   ...:     

In [3]: test_obj = Test()

In [4]: test_obj.test2 = test_function

In [5]: Test.test3 = test_function

In [6]: test_obj.test1()
<__main__.Test object at 0x7f1c798d6c10>

In [7]: type(test_obj.test1)
Out[7]: instancemethod

In [8]: test_obj.test2()
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-9-b50a9d669b63> in <module>()
----> 1 test_obj.test2()

TypeError: test_function() takes exactly 1 argument (0 given)

In [9]: type(test_obj.test2)
Out[9]: function

In [10]: test_obj.test3()
<__main__.Test object at 0x7f1c798d6c10>

In [11]: type(test_obj.test3)
Out[11]: instancemethod
Hieran schieht man, dass Methoden nicht einfach Funktionsattribute am Exemplar sind, sondern die Funktionen zu Methoden "umdekoriert" werden (Typ ändert sich). Dabei wird das `self` relevant, auf Pythonebene wird `self.methodA(attr1)` zu `function_behind_methodA(self, attr1)` übersetzt. Im obigen Beispielcode kann man das für `test_obj.test2` von Hand machen per `test_obj.test2(test_obj)`. Für Funktionsattribute auf Klassenebene macht Python das automatisch, daher funktioniert `test_obj.test3` wie erwartet.
Antworten