"TclError: invalid command name ".14846800.148467[...]"

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
Eragon314
User
Beiträge: 2
Registriert: Dienstag 19. November 2013, 08:57

Guten morgen,

ich arbeite seit den letzten Schulstunden an einer Ampelkreuzung.
Ich habe 3 Klassen und ein "Hauptprogramm".
ampel.py ist die Klasse für die Autoampeln.
fu_ampel.py ist die Klasse für die Fußgängerampeln.
ampelmanager.py ist von meinem Lehrer vorgegeben, damit es einfacher ist die Amepln zu schalten.


Mein Problem:

Die Lampen werden nicht "aktualisiert" und wenn ich das Fenster schließe kommt bei mir der Fehler aus der Überschrift.
Er verweist auf Zeile 1193 und Zeile 1184 der "__init__.py" (config???) und auf einen Fehler im Hauptprogramm Zeile 230 ---> def Zeile 16. In meinem Kurs kann mir niemand inkl. Lehrer weiterhelfen :K

Das Hauptprogramm ist noch nicht perfekt und vor allem ziemlich umständlich geschrieben xD

Ich hoffe es kann mir hier jemand helfen :)

MfG

~eragon


ampel.py

Code: Alles auswählen

class Ampel(object):

    __slots__ = ('zustand')

    def __init__(self, anfangszustand):

        # nachher:
        # Ein Objekt der Klasse Ampel ist erzeugt.
        # Der Wert des Attributs zustand wird auf den übergebenen
        # Parameter gesetzt.

        self.zustand = anfangszustand

    def setZustand(self, z):

        #  vorher:
        # Der Wert des Attributs zustand beschreibt eine Ampelphase.
        # nachher:
        # Dem Attribut zustand ist der Wert des übergebenen Parameters
        # z zugewiesen.

        self.zustand = z

    def getZustand(self):

        # Die Funktion ändert den Objektzustand nicht.
        # Die Funktion liefert als Ergebnis den Wert von zustand zurück.

        return self.zustand

    def schalten(self):

        #  vorher:
        # Der Wert des Attributs zustand beschreibt eine Ampelphase.
        # nachher:
        # Der Wert des Attributs zustand beschreibt die nächste Phase gemäß
        # des üblichen Ampelzyklus "rot -> rotgelb > gruen -> gelb -> rot".

        if self.zustand == 'rot':
            self.zustand = 'rotgelb'
        elif self.zustand == 'rotgelb':
            self.zustand = 'gruen'
        elif self.zustand == 'gruen':
            self.zustand = 'gelb'
        elif self.zustand == 'gelb':
            self.zustand = 'rot'

    def getLampen(self):

        # Die Funktion ändert den Objektzustand nicht.
        # Die Funktion liefert als Ergebnis ein Tripel aus Wahrheitswerten,
        # die den zur Phase passenden Lampenzustand in der Reihenfolge
        # (Lampe-rot, Lampe-gelb, Lampe-grün) beschreibt.

        if self.zustand == 'rot':
            lampen = (True, False, False)
        elif self.zustand == 'rotgelb':
            lampen = (True, True, False)
        elif self.zustand == 'gruen':
            lampen = (False, False, True)
        elif self.zustand == 'gelb':
            lampen = (False, True, False)
        return lampen
f_ampel.py

Code: Alles auswählen

class F_Ampel(object):

    __slots__ = ('zustand')

    def __init__(self, anfangszustand):

        # nachher:
        # Ein Objekt der Klasse Ampel ist erzeugt.
        # Der Wert des Attributs zustand wird auf den übergebenen
        # Parameter gesetzt.

        self.zustand = anfangszustand

    def setZustand(self, z):

        #  vorher:
        # Der Wert des Attributs zustand beschreibt eine Ampelphase.
        # nachher:
        # Dem Attribut zustand ist der Wert des übergebenen Parameters
        # z zugewiesen.

        self.zustand = z

    def getZustand(self):

        # Die Funktion ändert den Objektzustand nicht.
        # Die Funktion liefert als Ergebnis den Wert von zustand zurück.

        return self.zustand

    def schalten(self):

        #  vorher:
        # Der Wert des Attributs zustand beschreibt eine Ampelphase.
        # nachher:
        # Der Wert des Attributs zustand beschreibt die nächste Phase gemäß
        # des üblichen Ampelzyklus "rot -> rotgelb > gruen -> gelb -> rot".

        if self.zustand == 'rot':
            self.zustand = 'rot2'
        elif self.zustand == 'rot2':
            self.zustand = 'gruen'
        elif self.zustand == 'gruen':
            self.zustand = 'gruen2'
        elif self.zustand == 'gruen2':
            self.zustand = 'rot'

    def getLampen(self):

        # Die Funktion ändert den Objektzustand nicht.
        # Die Funktion liefert als Ergebnis ein Tripel aus Wahrheitswerten,
        # die den zur Phase passenden Lampenzustand in der Reihenfolge
        # (Lampe-rot, Lampe-gelb, Lampe-grün) beschreibt.

        if self.zustand == 'rot':
            lampen = (True, False)
        elif self.zustand == 'rot2':
            lampen = (True, False)
        elif self.zustand == 'gruen':
            lampen = (False, True)
        elif self.zustand == 'gruen2':
            lampen = (False, True)
        return lampen
ampelmanager.py

Code: Alles auswählen

#------------------------------------------------------------------------------
# Ampel
#------------------------------------------------------------------------------

from ampel import *
from f_ampel import *

#------------------------------------------------------------------------------
# Ampelmanager
#------------------------------------------------------------------------------

class AmpelManager(object):
    def __init__(self):
        self.ampel1 = None
        self.ampel2 = None
        self.ampel3 = None
        self.ampel4 = None
        self.f_ampel1 = None
        self.f_ampel2 = None
        self.f_ampel3 = None
        self.f_ampel4 = None

    def schalteAmpeln(self):
        self.ampel1.schalten()
        self.ampel2.schalten()
        self.ampel3.schalten()
        self.ampel4.schalten()
        self.f_ampel1.schalten()
        self.f_ampel2.schalten()
        self.f_ampel3.schalten()
        self.f_ampel4.schalten()
Das Hauptprogramm:

Code: Alles auswählen

##------------------------------------------------------------------------------
##   Header
##------------------------------------------------------------------------------

from tkinter import *
from ampelmanager import *
from ampel import *
from f_ampel import *

##------------------------------------------------------------------------------
##   Defs
##------------------------------------------------------------------------------

def anzeigeAktualisierenA1(lampeRot, lampeGelb, lampeGruen):
    if lampeRotA1:
        labelRotA1.config(background='red')
    else:
        labelRotA1.config(background='gray')
    if lampeGelbA1:
        labelGelbA1.config(background='yellow')
    else:
        labelGelbA1.config(background='gray')
    if lampeGruenA1:
        labelGruenA1.config(background='green')
    else:
        labelGruenA1.config(background='gray')

def anzeigeAktualisierenA2(lampeRot, lampeGelb, lampeGruen):
    if lampeRotA2:
        labelRotA2.config(background='red')
    else:
        labelRotA2.config(background='gray')
    if lampeGelbA2:
        labelGelbA2.config(background='yellow')
    else:
        labelGelbA2.config(background='gray')
    if lampeGruenA2:
        labelGruenA2.config(background='green')
    else:
        labelGruenA2.config(background='gray')

def anzeigeAktualisierenA3(lampeRot, lampeGelb, lampeGruen):
    if lampeRotA3:
        labelRotA3.config(background='red')
    else:
        labelRotA3.config(background='gray')
    if lampeGelbA3:
        labelGelbA3.config(background='yellow')
    else:
        labelGelbA3.config(background='gray')
    if lampeGruenA3:
        labelGruenA3.config(background='green')
    else:
        labelGruenA3.config(background='gray')

def anzeigeAktualisierenA4(lampeRot, lampeGelb, lampeGruen):
    if lampeRotA4:
        labelRotA4.config(background='red')
    else:
        labelRotA4.config(background='gray')
    if lampeGelbA4:
        labelGelbA4.config(background='yellow')
    else:
        labelGelbA4.config(background='gray')
    if lampeGruenA4:
        labelGruenA4.config(background='green')
    else:
        labelGruenA4.config(background='gray')

def anzeigeAktualisierenFuA1(lampeRot, lampeGruen):
    if lampeRotFuA1:
        labelRotFuA1.config(background='red')
    else:
        labelRotFuA1.config(background='gray')
    if lampeGruenFuA1:
        labelGruenFuA1.config(background='green')
    else:
        labelGruenFuA1.config(background='gray')

def anzeigeAktualisierenFuA2(lampeRot, lampeGruen):
    if lampeRotFuA2:
        labelRotFuA2.config(background='red')
    else:
        labelRotFuA2.config(background='gray')
    if lampeGruenFuA2:
        labelGruenFuA2.config(background='green')
    else:
        labelGruenFuA2.config(background='gray')

def anzeigeAktualisierenFuA3(lampeRot, lampeGruen):
    if lampeRotFuA3:
        labelRotFuA3.config(background='red')
    else:
        labelRotFuA3.config(background='gray')
    if lampeGruenFuA3:
        labelGruenFuA3.config(background='green')
    else:
        labelGruenFuA3.config(background='gray')

def anzeigeAktualisierenFuA4(lampeRot, lampeGruen):
    if lampeRotFuA4:
        labelRotFuA4.config(background='red')
    else:
        labelRotFuA4.config(background='gray')
    if lampeGruenFuA4:
        labelGruenFuA4.config(background='green')
    else:
        labelGruenFuA4.config(background='gray')

##------------------------------------------------------------------------------
##   GUI
##------------------------------------------------------------------------------

fenster = Tk()
fenster.title("Kreuzung")
fenster.geometry("500x500")

frameStraße = Frame(master=fenster, background = 'darkgray')

frameWiese1 = Frame(master=fenster, background = 'darkgreen')
frameWiese1.place(width=180, height =180)

frameWiese2 = Frame(master=fenster, background = 'darkgreen')
frameWiese2.place(x=320, width=180, height =180)

frameWiese3 = Frame(master=fenster, background = 'darkgreen')
frameWiese3.place(y=320, width=180, height =180)

frameWiese4 = Frame(master=fenster, background = 'darkgreen')
frameWiese4.place(x=320, y=320, width=180, height =180)

frameAmpel1 = Frame(master=frameWiese1, background = 'darkgray')
frameAmpel1.place(x=145, y=105, width=25, height =67)

frameAmpel2 = Frame(master=frameWiese2, background = 'darkgray')
frameAmpel2.place(x=10, y=145, width=67, height =25)

frameAmpel3 = Frame(master=frameWiese3, background = 'darkgray')
frameAmpel3.place(x=105, y=10, width=67, height =25)

frameAmpel4 = Frame(master=frameWiese4, background = 'darkgray')
frameAmpel4.place(x=10, y=10, width=25, height =67)

frameFuAmpel1 = Frame(master=frameWiese1, background = 'darkgray')
frameFuAmpel1.place(x=118, y=125, width=25, height =47)

frameFuAmpel2 = Frame(master=frameWiese2, background = 'darkgray')
frameFuAmpel2.place(x=10, y=118, width=47, height =25)

frameFuAmpel3 = Frame(master=frameWiese3, background = 'darkgray')
frameFuAmpel3.place(x=125, y=37, width=47, height =25)

frameFuAmpel4 = Frame(master=frameWiese4, background = 'darkgray')
frameFuAmpel4.place(x=37, y=10, width=25, height =47)

labelRotA1 = Label(master=frameAmpel1, background='gray')
labelRotA1.place(x=4, y=4, width=17, height=17)
labelGelbA1 = Label(master=frameAmpel1, background='gray')
labelGelbA1.place(x=4, y=25, width=17, height=17)
labelGruenA1 = Label(master=frameAmpel1, background='gray')
labelGruenA1.place(x=4, y=46, width=17, height=17)

labelRotA2 = Label(master=frameAmpel2, background='gray')
labelRotA2.place(x=4, y=4, width=17, height=17)
labelGelbA2 = Label(master=frameAmpel2, background='gray')
labelGelbA2.place(x=25, y=4, width=17, height=17)
labelGruenA2 = Label(master=frameAmpel2, background='gray')
labelGruenA2.place(x=46, y=4, width=17, height=17)

labelRotA3 = Label(master=frameAmpel3, background='gray')
labelRotA3.place(x=4, y=4, width=17, height=17)
labelGelbA3 = Label(master=frameAmpel3, background='gray')
labelGelbA3.place(x=25, y=4, width=17, height=17)
labelGruenA3 = Label(master=frameAmpel3, background='gray')
labelGruenA3.place(x=46, y=4, width=17, height=17)

labelRotA4 = Label(master=frameAmpel4, background='gray')
labelRotA4.place(x=4, y=4, width=17, height=17)
labelGelbA4 = Label(master=frameAmpel4, background='gray')
labelGelbA4.place(x=4, y=25, width=17, height=17)
labelGruenA4 = Label(master=frameAmpel4, background='gray')
labelGruenA4.place(x=4, y=46, width=17, height=17)

labelRotFuA1 = Label(master=frameFuAmpel1, background='gray')
labelRotFuA1.place(x=4, y=4, width=17, height=17)
labelGruenFuA1 = Label(master=frameFuAmpel1, background='gray')
labelGruenFuA1.place(x=4, y=25, width=17, height=17)

labelRotFuA2 = Label(master=frameFuAmpel2, background='gray')
labelRotFuA2.place(x=4, y=4, width=17, height=17)
labelGruenFuA2 = Label(master=frameFuAmpel2, background='gray')
labelGruenFuA2.place(x=25, y=4, width=17, height=17)

labelRotFuA3 = Label(master=frameFuAmpel3, background='gray')
labelRotFuA3.place(x=4, y=4, width=17, height=17)
labelGruenFuA3 = Label(master=frameFuAmpel3, background='gray')
labelGruenFuA3.place(x=25, y=4, width=17, height=17)

labelRotFuA4 = Label(master=frameFuAmpel4, background='gray')
labelRotFuA4.place(x=4, y=4, width=17, height=17)
labelGruenFuA4 = Label(master=frameFuAmpel4, background='gray')
labelGruenFuA4.place(x=4, y=25, width=17, height=17)

fenster.mainloop()

##------------------------------------------------------------------------------
##   Code
##------------------------------------------------------------------------------

ampel1 = Ampel('rot')
ampel2 = Ampel('gruen')
ampel3 = Ampel('rot')
ampel4 = Ampel('gruen')
f_ampel1 = F_Ampel('gruen')
f_ampel2 = F_Ampel('rot')
f_ampel3 = F_Ampel('gruen')
f_ampel4 = F_Ampel('rot')

ampelmanager = AmpelManager()
ampelmanager.ampel1 = ampel1
ampelmanager.ampel2 = ampel2
ampelmanager.ampel3 = ampel3
ampelmanager.ampel4 = ampel4
ampelmanager.f_ampel1 = f_ampel1
ampelmanager.f_ampel2 = f_ampel2
ampelmanager.f_ampel3 = f_ampel3
ampelmanager.f_ampel4 = f_ampel4

(lampeRotA1, lampeGelbA1, lampeGruenA1) = ampel1.getLampen()
anzeigeAktualisierenA1(lampeRotA1, lampeGelbA1, lampeGruenA1)
(lampeRotA2, lampeGelbA2, lampeGruenA2) = ampel2.getLampen()
anzeigeAktualisierenA2(lampeRotA2, lampeGelbA2, lampeGruenA2)
(lampeRotA3, lampeGelbA3, lampeGruenA3) = ampel3.getLampen()
anzeigeAktualisierenA3(lampeRotA3, lampeGelbA3, lampeGruenA3)
(lampeRotA4, lampeGelbA4, lampeGruenA4) = ampel4.getLampen()
anzeigeAktualisierenA4(lampeRotA4, lampeGelbA4, lampeGruenA4)

(lampeRotFuA1, lampeGruenFuA1) = f_ampel1.getLampen()
anzeigeAktualisierenFuA1(lampeRotFuA1, lampeGruenFuA1)
(lampeRotFuA2, lampeGruenFuA2) = f_ampel2.getLampen()
anzeigeAktualisierenFuA2(lampeRotFuA2, lampeGruenFuA2)
(lampeRotFuA3, lampeGruenFuA3) = f_ampel3.getLampen()
anzeigeAktualisierenFuA3(lampeRotFuA3, lampeGruenFuA3)
(lampeRotFuA4, lampeGruenFuA4) = f_ampel4.getLampen()
anzeigeAktualisierenFuA4(lampeRotFuA4, lampeGruenFuA4)


for i in range(8):
    ampelmanager.schalteAmpeln()
    (lampeRot, lampeGelb, lampeGruen) = ampel1.getLampen()
    anzeigeAktualisierenA1(lampeRot, lampeGelb, lampeGruen)
    (lampeRot, lampeGelb, lampeGruen) = ampel2.getLampen()
    anzeigeAktualisierenA2(lampeRot, lampeGelb, lampeGruen)
    (lampeRot, lampeGelb, lampeGruen) = ampel3.getLampen()
    anzeigeAktualisierenA3(lampeRot, lampeGelb, lampeGruen)
    (lampeRot, lampeGelb, lampeGruen) = ampel4.getLampen()
    anzeigeAktualisierenA4(lampeRot, lampeGelb, lampeGruen)

    (lampeRot, lampeGruen) = f_ampel1.getLampen()
    anzeigeAktualisierenFuA1(lampeRot, lampeGruen)
    (lampeRot, lampeGruen) = f_ampel2.getLampen()
    anzeigeAktualisierenFuA2(lampeRot, lampeGruen)
    (lampeRot, lampeGruen) = f_ampel3.getLampen()
    anzeigeAktualisierenFuA3(lampeRot, lampeGruen)
    (lampeRot, lampeGruen) = f_ampel4.getLampen()
    anzeigeAktualisierenFuA4(lampeRot, lampeGruen)
Sirius3
User
Beiträge: 17750
Registriert: Sonntag 21. Oktober 2012, 17:20

Hallo Eragon314,
den Code will sich glaube ich niemand freiwillig anschauen. Kannst Du das Problem in einem Minimalbeispiel reproduzieren?

Noch ein paar Anmerkungen zum Programmierstil an sich:
Es ist unüblich in Python für jede Klasse ein eigenes .py-File zu haben. Man kann und sollte mehrere Klassen in eine Datei packen, wenn sie so eng wie hier miteinander zu tun haben.
__slots__ sollte man im Allgemeinen nicht verwenden. Es ist kein Mechanismus um die möglichen Attribute einzuschränken. So etwas gibt es unter Python nicht. Es gibt nur sehr spezielle Fälle, wo __slots__ wirklich Sinn hat.
Setter und Getter gibt es in Python auch nicht. Sie erzeugen nur unnötigen Code, der nie gebraucht wird. Die Aufgabe von setZustand z.B. kann einfach durch direktes Zuweisen des Attributs gemacht werden. Ebenso kann obj.zustand auch direkt gelesen werden, ohne dass es eine spezielle getZustand-Methode bräuchte.
*-importe sind fast immer zu vermeiden, da sie Klassen- und Funktionsnamen in den eigenen Namensraum übernehmen, man aber nicht weiß welche. Das führt zu ungewollten Überschneidungen, die zu sehr schwer zu findenden Fehlern führt. Importiert werden sollten immer nur konkrete Namen: "from ampel import Ampel"
Im Hauptprogramm hast Du viel kopierten Code. Das läßt sich vermeiden, indem Du eine Ampel-Liste erzeugst und nicht die Variablennamen durchnummerierst.

Der Code nach mainloop wird erst ausgeführt, wenn das Fenster wieder geschlossen ist. Dann ist das Fenster aber weg und es gibt seltsame Fehler, wenn man trotzdem darauf zugreifen will.
Eragon314
User
Beiträge: 2
Registriert: Dienstag 19. November 2013, 08:57

oh mann xD
mainloop erstmal nach ganz unten gemacht und jetzt wird es aktualisiert *lol*

ich glaub daran lag es xD
das mit den classen in nur einer datei werd ich mir merken :)

die klasse ampel hab ich auch von unserm lehrer^^ naja...
dickes DANKESCHÖN!!!

mit welchem befehl erzeuge ich so eine Liste?
dass das so ewig lang is, hab ich auch schon gemerkt, bloß bis jetzt noch nicht herausgefunden, wie ich es "besser" mache

nochmal danke
~eragon
BlackJack

@Eragon314: Noch ein paar Anmerkungen zu dem Quelltext.

Die Kommentare mit den Vor- und Nachbedingungen wären in Docstrings besser aufgehoben, denn sie gehören zur Dokumentation der Schnittstelle.

Einbuchstabige Namen sind in den meisten Fällen keine gute Idee. Für klassische Zählvariablen und in sehr begrenzten Bereichen wie „list comprehensions”, Generator- und ``lambda``-Ausdrücken geht das, aber als Methodenargument ein `z` für `zustand` ist eine unnötige Abkürzung. Ähnliches gilt für zusammengesetze Namen. `f_ampel` wäre so ein Beispiel. Namen sollten dem Leser Informationen vermitteln, nämlich was die Werte dahinter bedeuten, und nicht zum raten nötigen. `fussgaengerampel` ist *deutlich* aussagekräftiger.

Die ganzen ``if``/``elif``-Konstrukte in den `schalten()` und `getLampen()`-Methoden liessen sich durch Wörterbücher ersetzen. Der Zustand in Form von Zeichenketten ist auch irgendwo redundant, das könnte man direkt durch die Tupel ersetzen. Die könnte man an Namen binden die den jetzigen Zeichenketten entsprechen. Zumindest bei `Ampel` geht das. Bei `F_Ampel` gibt es ja verschiedene Zustandswerte für letztendlich den jeweils gleichen Zustand. Das hätte ich anders gelöst. Wenn nur bei jedem x. Mal der Zustand geändert wird, kann man dafür auch einen Zähler einführen.

Die beiden Ampel-Implementierungen sind auch viel zu ähnlich um sie in zwei „verschiedene” Klassen zu stecken. Von der Programmlogik her ist `F_Ampel` eigentlich eine Kopie von `Ampel`, nur die Werte mit denen gearbeitet wird unterscheiden sich. In so einem Fall würde man nur eine Ampel ausprogrammieren, der man die Zustände und Zustandsfolge als Werte übergeben kann.

Das es *tatsächlich* eine Kopie ist, sieht man daran, dass Du die Kommentare unverändert gelassen hast und die Beschreibungen dort jetzt gar nicht mehr zum Code passen. Das ist IMHO eine wirklich schlimme Sache. Kein Scherz. Das ist etwas was Programmierer später zum Verzeifeln bringen kann, weil damit im Ernstfall sämtliche Dokumentation und Kommentare wertlos werden, weil man ihnen einfach nicht mehr vertrauen kann ob sie nun zutreffend sind oder nicht. Dann hat man trotz Kommentaren im Grunde einen unkommentierten Quelltext vor sich.

Nochmal zu Namen: `Manager` ist ein total nichtssagendes Füllwort was man als Warnzeichen sehen sollte. Das benutzen Leute die zu faul sind sich einen ordentlichen Namen auszudenken oder die keinen gefunden haben. Wenn einem tatsächlich nichts besseres einfällt, dann lässt man es einfach weg und benennt die Klasse nach der Mehrzahl des Datentyps den die Klasse verwaltet/zusammenfasst. Also einfach `Ampeln` statt `AmpelManager`. In diesem Falle gibt es aber einen Recht naheliegenden Begriff der zusammengehörige Ampeln bezeichnet: `Ampelanlage`.

Die Ampeln sollte man *in* dem Objekt für die Ampelanlage erzeugen. Eine `__init__()` die alle Attribute auf `None` setzt und ein Objekt das erwartet, dass man die dann einzeln von aussen setzt ist kein guter Stil. Dann muss man darauf vertrauen das irgendwo von aussen die Ampeln so gesetzt werden, dass die gesamte Ampelanlage intern einen konsistenten Zustand hat.

Für eine realistischere Umsetzung würde man die Ampeln auch nicht einzeln sich selbst schalten lassen, sondern die Schaltlogik in die Ampelanlage stecken, denn die Ampeln sind ja keineswegs unabhängig voneinander. Bei diesem Standardkreuzungsbeispiel hat man aus Sicht der Schaltlogik keine acht Ampeln sondern vier Ampelpaare die jeweils immer das gleiche Anzeigen. Und die kann man wiederum zu zwei Gruppen zuordnen wobei die Anzeige der einen Gruppe direkt von der Anzeige der anderen abhängt.

Bei der GUI würde man einen Typ für die Anzeige einer Ampel schreiben. Damit würde man sich schon mal eine Menge an kopiertem Quelltext sparen. So ziemlich immer wenn man anfängt Quelltext zu kopieren und leicht in den Werten anzupassen macht man etwas falsch. Dann sollte man eigentlich Werte herausziehen und eine Schleife über diese Werte schreiben oder den sich wiederholenden Code in eine Funktion oder Klasse herausziehen, oder beides.
mutetella
User
Beiträge: 1695
Registriert: Donnerstag 5. März 2009, 17:10
Kontaktdaten:

Sirius3 hat geschrieben:Es gibt nur sehr spezielle Fälle, wo __slots__ wirklich Sinn hat.
Ich habe zufällig gerade diesen Blogeintrag gelesen, in dem ein solcher Fall beschrieben wird.

mutetella
Entspanne dich und wisse, dass es Zeit für alles gibt. (YogiTea Teebeutel Weisheit ;-) )
Benutzeravatar
snafu
User
Beiträge: 6740
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

mutetella hat geschrieben:
Sirius3 hat geschrieben:Es gibt nur sehr spezielle Fälle, wo __slots__ wirklich Sinn hat.
Ich habe zufällig gerade diesen Blogeintrag gelesen, in dem ein solcher Fall beschrieben wird.
Ab Python 3.3 dürfte das Problem mit dem Speicherverbrauch verringert sein. Siehe Changelog-Eintrag:
Issue #13903: Implement PEP 412. Individual dictionary instances can now share their keys with other dictionaries. Classes take advantage of this to share their instance dictionary keys for improved memory and performance.
http://docs.python.org/3.3/whatsnew/changelog.html#id62

Ob damit tatsächlich soviel eingespart wird, wie es in der Variante mit ``__slots__`` in deinem Link beschrieben wird, kann ich allerdings nicht beurteilen.
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Im Artikel gibt es genau dazu einen Kommentar:
Ben Hoyt hat geschrieben:No, we haven’t tried PyPy yet, though we’re definitely keeping our eye on it! Incidentally, Python 3.3 mitigates this issue somewhat with PEP 412′s “key-sharing dictionary” implementation: http://www.python.org/dev/peps/pep-0412/ It’s not as good as slots, but it uses about half the memory of ordinary classes in a quick test I did.
Insofern sollte man immer noch ein Auge darauf haben, wenn man keine NamedTuple fuer Datenklassen benutzt.
Benutzeravatar
snafu
User
Beiträge: 6740
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

cofi hat geschrieben:Im Artikel gibt es genau dazu einen Kommentar:
Ben Hoyt hat geschrieben:No, we haven’t tried PyPy yet, though we’re definitely keeping our eye on it! Incidentally, Python 3.3 mitigates this issue somewhat with PEP 412′s “key-sharing dictionary” implementation: http://www.python.org/dev/peps/pep-0412/ It’s not as good as slots, but it uses about half the memory of ordinary classes in a quick test I did.
Insofern sollte man immer noch ein Auge darauf haben, wenn man keine NamedTuple fuer Datenklassen benutzt.
...oder wenn man Datenhaltung und Funktionalität vermischt, sodass NamedTuples etwas umständlich werden.

Reine Datencontainer würde ich grundsätzlich als NamedTuple implementieren. Bei dynamisch erzeugten Daten eher nicht. Aber machen Slots bei einer dynamischen Erzeugung eigentlich Sinn? Bin da nicht so im Thema drin...

EDIT: Ok, vergesst die letzte Frage. ^^
Antworten