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.
Benutzeravatar
Schwarzer Wolf
User
Beiträge: 56
Registriert: Donnerstag 5. Januar 2017, 05:24

Ich Grüße Euch

Langsam klappt es mit der OOP bei mir etwas besser. Aber nun hab ich ein Problem und komme seit etlichen Stunden 'Trail and Error' nicht mehr weiter :K :

Ich habe mal ein Minibeispiel geschrieben, von daher bitte ich um Verzeihung bei den Bezeichnern.

Code: Alles auswählen

import temp


class Admin:
    def __init__(self):
        self.z = temp
        self.z.Test.show()


def main():
    Admin()


if __name__ == '__main__':
    main()

Code: Alles auswählen

class Test:
    def __init__(self):
        self.x = []

    def show(self, a):
        self.x += [a]
Egal wie ich den Import nun probiere, er möchte immer noch 'self' mit dazu haben. Wie mache ich es, dass nur 'a' eingegeben werden muss? Dass 'a' im Beispiel fehlt, ist mir klar. :D

Hier der vermutlich relevante Teil der Fehlermeldung:
TypeError: show() missing 2 required positional arguments: 'self' and 'a'
Danke im Voraus und einen angenehmen Sonntag
Wer in der Wildnis lebt, muss zum Wolf werden, oder als Schaf sterben.
(Syrisches Sprichwort)
BlackJack

@Schwarzer Wolf: Das Beispiel ist unnötig kompliziert um das Problem zu verdeutlichen. Die `Admin`-Klasse braucht man dafür überhaupt nicht. Das hier reicht:

Code: Alles auswählen

import temp
temp.Test.show()
Was denkst Du denn was `self` hier für einen Wert beim Aufruf haben sollte? Das ist ja ein Exemplar des Typs `Test`, nur wird hier ja nie eines erstellt. Du rufst `show()` auf der *Klasse* `Test` auf. Und da muss man dann beide Argumente übergeben. Wobei das eher unüblich ist, ausser beim Aufruf von Methoden einer Basisklasse.
Benutzeravatar
pillmuncher
User
Beiträge: 1484
Registriert: Samstag 21. März 2009, 22:59
Wohnort: Pfaffenwinkel

Schwarzer Wolf hat geschrieben:'Trail and Error'
SCNR: The Trail of the Lonesome Pine
In specifications, Murphy's Law supersedes Ohm's.
Benutzeravatar
snafu
User
Beiträge: 6738
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

@Schwarzer Wolf:
__init__() ist zur Initialisierung, jedoch nicht zur Rückgabe von Werten gedacht. Es sind auch einige weitere Änderungen an deinem Code nötig, damit er halbwegs sinnvoll arbeitet. Mit einem ordentlichen Schuss an Interpretation (und Ignorieren des Sinns) würde es dann in etwa so aussehen:

Code: Alles auswählen

class Viewer:
    def __init__(self, data=[]):
        self.data = data or []

    def show(self, additional):
        self.data.append(additional)
        return self.data

Code: Alles auswählen

from viewer import Viewer

class Admin:
    def __init__(self, viewer):
        self.viewer = viewer

    def show(self):
        return self.viewer.show()


def main():
    admin = Admin(Viewer())
    print(admin.show())


if __name__ == '__main__':
    main()
Ich glaube anhand deines Codes ja nicht, dass du schon bereit für OOP bist, aber musst du für dich selbst entscheiden...
BlackJack

@snafu: Wo hat der OP denn eine Rückgabe in `__init__()` versucht?

Die Liste als Defaultwert bei Dir würde ich als Fehler ansehen. Und das ``data or []`` eigentlich auch. Das ist zumindest fehleranfällig.
Benutzeravatar
snafu
User
Beiträge: 6738
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

BlackJack hat geschrieben:@snafu: Wo hat der OP denn eine Rückgabe in `__init__()` versucht?
Bei self.z.Test.show() hatte ich angenommen, dass ein Wert zurückgeliefert wird. Könnte sich aber natürlich auch um eine GUI-Ausgabe handeln...
BlackJack hat geschrieben:Die Liste als Defaultwert bei Dir würde ich als Fehler ansehen. Und das ``data or []`` eigentlich auch. Das ist zumindest fehleranfällig.
Warum ist das ein Fehler? Es wird ja bewusst nicht das Default-Argument verwendet, sondern es dient nur als Kennzeichung des erwarteten Typs. Klar kann man auch einen Test auf if data is None einbauen. Ich sehe die etwas großzügigere Auslegung via or aber nicht unbedingt als Fehler an.
BlackJack

@snafu: Bei ``self.z.Test.show()`` wird aber nichts zurückgegeben und mit einer `__init__()` hat das alles immer noch nichts zu tun.

Zu Deinem Code: Sorry, aber das sind IMHO beides Sachen die man nicht verwenden sollte und schon gar nicht Anfängern zeigen sollte, weil beides zu ”überraschenden” Effekten führen kann. Das Du da jetzt eine ”sichere” Kombination hast, wäre bei einem Anfänger eher ein Glücksfall.
Benutzeravatar
kbr
User
Beiträge: 1487
Registriert: Mittwoch 15. Oktober 2008, 09:27

@snafu: die Defaultliste in der Parameterübergabe wird einmal zur Compile-Time erzeugt und später während der Programmausführung immer wiederverwendet. Sie wird nicht bei jedem Funktionsaufruf neu angelegt. Das gilt auch für Dictionaries.

Probiere einmal das Folgende:

Code: Alles auswählen

def show(data=[], modifier=8):
    data.append(modifier)
    return data
    
print(show())
print(show(data=[1,2], modifier=5))
print(show())
Sirius3
User
Beiträge: 17741
Registriert: Sonntag 21. Oktober 2012, 17:20

@snafu: Wenn Du das Default-Argument sowieso nicht benutzt, warum dann eine leere Liste? Die Überraschung ist, dass sich ›Viewer(data)‹ bei ›data = ["a", "b"]‹ anders verhält als bei ›data = []‹. Ich halte es auch immer noch mit dem Grundsatz, dass eine Methode entweder den Zustand ändern soll, oder ihn zurückgeben, aber nicht beides gleichzeitig.

@kbr: ich glaube dieser Umstand ist snafu bekannt, daher ja das Konstrukt mit dem ›or‹. Die Liste wird nicht zur Compilezeit erzeugt, sondern dann, wenn die Funktion definiert wird.
Benutzeravatar
Schwarzer Wolf
User
Beiträge: 56
Registriert: Donnerstag 5. Januar 2017, 05:24

snafu hat geschrieben:Ich glaube anhand deines Codes ja nicht, dass du schon bereit für OOP bist, aber musst du für dich selbst entscheiden...
Bisher kam ich in den Kapiteln recht gut vorwärts und OOP wäre eben nun das Kapitel (nach ca. 300 Seiten). Wird ja vermutlich nichts bringen, nun wieder zurückzugehen zu Dingen, die ich mehr oder minder Gut kann oder weiterzugehen, da vermutlich Beispiele mit Klassen im weiteren Verlauf folgen werden.

@all

Ich poste mal beide Originalcodes aus dem Buch. Dieser ist nicht PEP 8 konform und es gibt in der Regel im Code von Michael so manche Dinge, die selbst mir als Anfänger sehr seltsam erscheinen. Vermutlich wird dann der Sinn des Codes klarer.

Normalerweise habe ich mir angewöhnt, die Bezeichner in Englisch zu machen. Da dies aber nur eine Übung ist, benutze ich Deutsche.

Es geht in der Übung um die Erstellung eines "Musical-Mangers" und seinem Backend. Zudem gibt es noch eine dritte .py Datei, die für die 'Ticketreservierung' ist. Diese habe ich weggelassen, da das Beispiel in "Manager" und "Mitarbeiter" unterteilt ist. Bei mir ist es ein Theater, anstatt eines Musicals.

Dadrunter werde ich meinen Code posten, den ich ein relativ frei dem Kopf geschrieben habe und an einigen Stellen verändert habe. Natürlich ist mein Code auch nur ein Teil des ganzen, da ich wie gesagt bis zu dieser Stelle der Übung recht gut vorwärts kam und nun an dieser Sache feststecke.
Mein Problem liegt im zweiten Skript von mir bei Zeile 45:

Code: Alles auswählen

self.daten.Theaterstueck.neue_auffuehrung(auffuehrung)
Zudem versuche ich PEP 8 konform zu arbeiten, und manche Dinge wie "-1" Initialisierungen in Skripten etc. von Michael ändere ich.

Hier beide Codes von Michael:

Code: Alles auswählen

#----------------------------------------------------
# Dateiname: musical.py
# Modul mit Klassen zur Modellierung eines Musicals
#
# Objektorientierte Programmierung mit Python
# Kap. 12 
# Michael Weigend 2.10.09
#----------------------------------------------------


# musical.py  - Modell eines Musicals
import pickle

class Musical: 
    def __init__(self, titel, eintrittspreis, saal):
       self.titel = titel
       self.eintrittspreis = eintrittspreis
       self.saal = saal
       self.vorstellungen = [] # Liste von Vorstellungen

    def getVorstellung(self, datum):
        """Rückgabe eines Vorstellungs-Objektes mit
        passendem Datum, falls vorhanden, sonst None"""        
        for vorstellung in self.vorstellungen:
          if vorstellung.datum == datum: return vorstellung
        # Nach dem return bricht die Ausführung der Funktion ab

    def neueVorstellung(self, vorstellung):
        """Objekt vorstellung wird in Liste eingefügt"""
        self.vorstellungen += [vorstellung]

    def __str__(self):                               #1
        beschreibung = '\n' + self.titel + '\n' + \
                       len(self.titel)*'=' + '\n'
        for vorstellung in self.vorstellungen:
            beschreibung += str(vorstellung) + '\n'
        return beschreibung 

class Vorstellung:
    def __init__(self, datum, beginn, saal ):
        self.datum = datum
        self.beginn = beginn
        self.saalbelegung = Saalbelegung(saal)
        self.saal = saal

    def __str__(self):                               #1
        beschreibung = self.datum + '\n' + \
        str(self.saalbelegung.getFreiePlaetze()) + \
        ' freie Plätze\n' 
        return beschreibung

class Saalbelegung:
    """pflegt Liste von Listen mit Platz-Objekten"""
    def __init__(self, saal):
        self.belegung = []
        self.saal = saal
        for i in range(len(saal.plaetzeProReihe)):   #2
            reihe = []
            for j in range(saal.plaetzeProReihe[i]):
                platz = Platz()
                reihe += [platz]
            self.belegung += [reihe]

    def buche(self, reihe, platz, zuschauer):        #3
        '''weist dem Platz platz in Reihe reihe einen
        Zuschauer zu'''
        if not self.belegung[reihe][platz].belegt():
           self.belegung[reihe][platz].belege(zuschauer)
           return 'Platz gebucht'
        else: return 'Platz schon belegt'

    def getFreiePlaetze(self):
        """liefert Anzahl der freien Plaetze"""
        frei=0
        for reihe in self.belegung:
            for platz in reihe:
                if not platz.belegt(): frei += 1
        return frei

    def __str__(self):                               #1
        beschreibung = 'Saalbelegung\n'
        beschreibung += '   Platz: 1  2  3  4  5  6  7  8  9  10 '
        beschreibung += '11 12 13 14\n'
        nr = 1                           # Reihennummer
        for reihe in self.belegung:
            beschreibung += 'Reihe ' + format(nr, '2d') + ': '
            for platz in reihe:
                beschreibung += str(platz)
            nr += 1
            beschreibung += '\n'         # neue Zeile
        return beschreibung

class Zuschauer:
    def __init__(self, name, tel):
        self.name, self.tel = name, tel

Code: Alles auswählen

#----------------------------------------------------
# Dateiname: musicalmanager.py
# Verwaltung eines Musicals - Manager
#
# Objektorientierte Programmierung mit Python
# Kap. 12 
# Michael Weigend 2.10.09
#----------------------------------------------------

# musicalmanager.py  - Verwaltung eines Musicals 
import pickle
from musical import *

class Manager:   
    __menuetext = """
    Musical-Manager
    ------------------
    (n)eue Vorstellung
    (U)eberblick Vorstellungen
    (E)nde
     """

    def __init__(self, datei):                        #1
        self.__datei = datei  
        self.__lade_musical()
        self.__run()

    def __run(self):                                  #2
        """ Menü und Verarbeitung von Auswahlen"""
        print (self.__menuetext)
        wahl = '-'
        while wahl not in ['e', 'E']:
          wahl = input('Auswahl: ')
          if wahl in ['n', 'N']:
            self.__neueVorstellung()
          elif wahl in ['U', 'u']: 
            print (str(self.__musical))
            print (self.__menuetext)
            wahl = input('Auswahl: ')
        print ("Danke für die Benutzung von Musical-Manager")
        self.__speichern()

    def __neueVorstellung(self):
        """Dialog zum Einrichten einer neuen Vorstellung"""
        datum = input('Termin: ')
        beginn = input('Beginn der Vorstellung: ')
        vorstellung = Vorstellung(datum, beginn, self.__musical.saal)
        self.__musical.neueVorstellung(vorstellung)

    def __neuesMusical(self):                        #3
        '''Dialog zur Definition eines neuen Musicals'''
        titel = input('Titel: ')
        eintrittspreis = float(input('Eintrittspreis: '))
        anzahl_reihen = int(input("Anzahl Sitzreihen: "))
        liste = []
        for i in range(anzahl_reihen):
            sitze = int(input("Sitze in Reihe " + str(i) + ": "))
            liste.append(sitze)                 
        saal = Saal(liste)
        self.__musical = Musical(titel, eintrittspreis, saal)

    def __lade_musical(self): 
        """Musical-Objekt wird geladen, falls Datei vorhanden
        sonst muss neues Musical definiert werden"""
        try:
            f = open(self.__datei, 'rb')  # lesen im Binärmodus
            self.__musical = pickle.load(f)
            f.close()
            print ('\n               W I L L K O M M E N')
            print ('beim Management-System für das Musical',
                   self.__musical.titel)
        except:
            print('Kein Musical gespeichert.')
            print('Richten Sie neues Musical ein.')
            self.__neuesMusical()

    def __speichern(self):                           
        """Musical-Objekt speichern """
        f = open(self.__datei, 'wb') # schreiben im Binärmodus
        pickle.dump(self.__musical, f)
        f.close()

m = Manager('daten/hairspray.txt')   # relative Adresse der Daten-Datei
Hier meine Codes:

Code: Alles auswählen

class Theaterstueck:
    def __init__(self, titel, eintrittspreis):
        self.titel = titel
        self.eintrittspreis = eintrittspreis
        self.auffuehrungen = []

    def zeige_auffuehrungen(self, datum):
        for auffuehrung in self.auffuehrungen:
            if auffuehrung.datum == datum:
                return auffuehrung

    def neue_auffuehrung(self, neu):
        self.auffuehrungen += [neu]


class Auffuehrung:
    def __init__(self, datum, beginn):
        self.datum = datum
        self.beginn = beginn

    def __str__(self):
        pass

Code: Alles auswählen

import pickle
import sys
import theater


class Theatermanager:
    def __init__(self, titel):
        self.titel = titel
        self.dateipfad = ('data/' + self.titel + '.data')
        self.daten = theater
        self.dateizugriff_lesen()
        self.menue()

    def dateizugriff_lesen(self):
        try:
            datei = open(self.dateipfad, 'rb')
            self.daten = pickle.load(datei)
            datei.close()
            print('Lade Theaterstück: ' + self.daten.titel)
            input('<ENTER> = Hauptmenü\n')
        except FileNotFoundError:
            print('Theaterstück', '"' + self.titel + '"', 'inexistent')
            input('<ENTER> = Hauptmenü\n')

    def dateizugriff_speichern(self):
        datei = open(self.dateipfad, 'wb')
        pickle.dump(self.daten, datei)
        datei.close()

    def theaterstueck_neu(self):
        while True:
            try:
                titel = input('Titel des Theaterstücks:')
                eintrittspreis = float(input('Eintrittspreis: '))
                self.daten = theater.Theaterstueck(titel, eintrittspreis)
                return
            except ValueError:
                print('Eingabe inkorrekt')
                continue

    def auffuehrung_neu(self):
            datum = input('Datum: ')
            beginn = input('Beginn: ')
            auffuehrung = theater.Auffuehrung(datum, beginn)
            self.daten.Theaterstueck.neue_auffuehrung(auffuehrung)

    def menue(self):
        text = '''Administraton:
        [1] - Neues Theaterstück
        [2] - Neue Aufführung
        [3] - Aufführungen

        [0] - Beenden'''

        while True:
            try:
                print(text)
                eingabe = int(input('Eingabe: '))
                if eingabe == 0:
                    sys.exit()
                elif eingabe == 1:
                    self.theaterstueck_neu()
                elif eingabe == 2:
                    self.auffuehrung_neu()
                elif eingabe == 3:
                    pass
                else:
                    continue
            except ValueError:
                continue
            self.dateizugriff_speichern()


def main():
    eingabe = input('Name des Theaterstücks: ')
    Theatermanager(eingabe)


if __name__ == '__main__':
    main()
Wer in der Wildnis lebt, muss zum Wolf werden, oder als Schaf sterben.
(Syrisches Sprichwort)
Benutzeravatar
kbr
User
Beiträge: 1487
Registriert: Mittwoch 15. Oktober 2008, 09:27

Sirius3 hat geschrieben:@kbr: ich glaube dieser Umstand ist snafu bekannt, daher ja das Konstrukt mit dem ›or‹.
Oops. Ich bin es so gewohnt keine mutable als defaults zu nehmen, da habe ich dies glatt nicht beachtet.
Sirius3
User
Beiträge: 17741
Registriert: Sonntag 21. Oktober 2012, 17:20

@Schwarzer Wolf: In getVorstellung ist die Einrückung nicht korret. Bei neueVorstellung sollte man append verwenden, statt eine einelementige Liste zu erzeugen. In Musical.__str__ sollte man dringend .join und .format benutzen. Zeilen mit `\` fortzusetzen ist eigentlich nie gut, da hinter dem Backslash kein Leerzeichen kommen darf, und daher subtile Fehler entstehen können. Pickle ist für Langzeitspeicherung kein gutes Format. Sternchenimporte vermeiden. Die Attribute in Manager haben zu viele Unterstriche. In Deinem Code hat sich auch ein += [xxx] statt eines append eingeschlichen. Auffuehrung.__str__ löschen, da es nichts sinnvolles tut.

In Theatermanager.__init__: Pfade setzt man mit os.path.join zusammen und nicht mit +, die Zuweisung hat auch zu viele Klammern. self.daten wird ein Modul zugewiesen, später eine Instanz von Theaterstueck, in auffuehrung_neu wird dann aber wieder über die Modulzuweisung die Klasse Theaterstueck referenziert. Normalerweise ist es nicht sinnvoll, einem Attribut ein Modul zuzuweisen. Hier macht es rein logisch keinen Sinn. Damit ist der Zugriff auf Theaterstueck auch nicht das, was Du eigentlich willst. Eine __init__-Methode sollte möglichst schnell ein Initialisiertes Objekt liefern. Durch den Aufruf von menue wird nie ein initialisiertes Objekt generiert. menue außerhalb von __init__ aufrufen.
In Theatermanager.dateizugriff_lesen: Dateien sollte man mit dem with-Statement. Pickel ist kein sinnvolles Dateiformat.
theaterstueck_neu: try-Blöcke sollten nur den Bereich umfassen, wo tatsächlich Fehleingaben erwartet werden, hier die Zeile mit float. Das continue ist überflüssig.
auffuehrung_neu: falsch Eingerückt
menue: niemals sys.exit in einer Methode verwenden. Einfach per return die Funktion verlassen.

Ein Theatermanager für nur ein Theaterstück ist unsinnig. Die Klasse hat nicht wirklich viel Status, sodass man die Klasse am besten durch Funktionen ersetzt. Warum hat der Theatermanager einen Stücktitel und das Theaterstück selbst auch? Der Titel in Theatermanager ist überflüssig - weg damit.
Benutzeravatar
Schwarzer Wolf
User
Beiträge: 56
Registriert: Donnerstag 5. Januar 2017, 05:24

Sirius3 hat geschrieben:@Schwarzer Wolf: In getVorstellung ist die Einrückung nicht korret. Bei neueVorstellung sollte man append verwenden, statt eine einelementige Liste zu erzeugen. In Musical.__str__ sollte man dringend .join und .format benutzen. Zeilen mit `\` fortzusetzen ist eigentlich nie gut, da hinter dem Backslash kein Leerzeichen kommen darf, und daher subtile Fehler entstehen können. Pickle ist für Langzeitspeicherung kein gutes Format. Sternchenimporte vermeiden. Die Attribute in Manager haben zu viele Unterstriche. In Deinem Code hat sich auch ein += [xxx] statt eines append eingeschlichen. Auffuehrung.__str__ löschen, da es nichts sinnvolles tut.
Das ist das Beispiel von Michael, also dem Verfasser des Buches "Python 3". Das er vieles nicht Konform macht ist mir bekannt. Von mir sind nur die beiden unteren Codes.

Ein Theatermanager für nur ein Theaterstück ist unsinnig. Die Klasse hat nicht wirklich viel Status, sodass man die Klasse am besten durch Funktionen ersetzt. Warum hat der Theatermanager einen Stücktitel und das Theaterstück selbst auch? Der Titel in Theatermanager ist überflüssig - weg damit.[/quote]
Das ist das Beispiel von Michael, also dem Verfasser des Buches "Python 3". Das er vieles nicht konform macht ist mir bekannt. Von mir sind nur die beiden unteren Codes.

So ist leider das Buchbeispiel. Muss mich ja mehr oder minder daran Orientieren, da dazu später auch noch Übungen vorkommen
Sirius3 hat geschrieben:Pfade setzt man mit os.path.join zusammen und nicht mit +
Das Thema hatte ich bisher noch nicht. War auch frei aus dem Kopf
Sirius3 hat geschrieben: self.daten wird ein Modul zugewiesen, später eine Instanz von Theaterstueck, in auffuehrung_neu wird dann aber wieder über die Modulzuweisung die Klasse Theaterstueck referenziert. Normalerweise ist es nicht sinnvoll, einem Attribut ein Modul zuzuweisen. Hier macht es rein logisch keinen Sinn. Damit ist der Zugriff auf Theaterstueck auch nicht das, was Du eigentlich willst.
So macht Michael es ungefähr im Buch auch, nur dass er eben im __init__ keine Zuweisung macht. Da gab es dann bei mir aber einen PEP 8 Fehler. Kannst Du mir ein Beispiel sagen, wie ich dass besser machen kann.
Sirius3 hat geschrieben:auffuehrung_neu: falsch Eingerückt
Verbessert.
Sirius3 hat geschrieben: theaterstueck_neu: try-Blöcke sollten nur den Bereich umfassen, wo tatsächlich Fehleingaben erwartet werden, hier die Zeile mit float. Das continue ist überflüssig.menue: niemals sys.exit in einer Methode verwenden. Einfach per return die Funktion verlassen.
Ok

Danke für die Hilfe bisher.
Wer in der Wildnis lebt, muss zum Wolf werden, oder als Schaf sterben.
(Syrisches Sprichwort)
BlackJack

@Schwarzer Wolf: Statt eines sinnlosen Wertes solltest Du einen sinnvollen Wert an das Attribut binden und nicht irgend ein Modul, was da ja auch nie benutzt wird. Sinnvoll für einen Wert für den es eigentlich noch gar keinen Wert gibt, könnte `None` sein. Was in Python der Wert für „kein Wert“/„nichts“ ist. Oder aber ein wie auch immer geartetes ”leeres” Objekt, das man so benutzen kann wie die tatsächlichen Werte an die das Attribut im Laufe des Programms gebunden wird. Dann braucht man sich keine Gedanken um eine Sonderbehandlung von `None` machen. Da `daten` ja wahrscheinlich die Theaterstücke repräsentieren soll, die der Theatermanager verwaltet, könnte das beispielsweise eine leere Liste sein.
Benutzeravatar
Schwarzer Wolf
User
Beiträge: 56
Registriert: Donnerstag 5. Januar 2017, 05:24

BlackJack hat geschrieben:@Schwarzer Wolf: Statt eines sinnlosen Wertes solltest Du einen sinnvollen Wert an das Attribut binden und nicht irgend ein Modul, was da ja auch nie benutzt wird. Sinnvoll für einen Wert für den es eigentlich noch gar keinen Wert gibt, könnte `None` sein. Was in Python der Wert für „kein Wert“/„nichts“ ist. Oder aber ein wie auch immer geartetes ”leeres” Objekt, das man so benutzen kann wie die tatsächlichen Werte an die das Attribut im Laufe des Programms gebunden wird. Dann braucht man sich keine Gedanken um eine Sonderbehandlung von `None` machen. Da `daten` ja wahrscheinlich die Theaterstücke repräsentieren soll, die der Theatermanager verwaltet, könnte das beispielsweise eine leere Liste sein.
Das habe ich zwischenzeitlich in meinem 'Trail and Error' auch mit 'None' gemacht, das Problem ist, dass noch immer der Fehler in Zeile 46 (theatermanager) angezeigt wird und er 'self' verlangt. :K
Wer in der Wildnis lebt, muss zum Wolf werden, oder als Schaf sterben.
(Syrisches Sprichwort)
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: 17741
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: 14528
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
Antworten