Problem mit init default

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
thomas15
User
Beiträge: 98
Registriert: Montag 7. April 2008, 19:07

Hallo alle!

Ich habe ein Problem das ich habe selbs loesen koennen, dessen Ursache mir aber unklar ist:

Ich habe eine Klasse

Code: Alles auswählen

class AngleList(AngleObject):
    """
    AngleList : Derives from AngleObject. Can be used to perform calculations on arbitrary rotation lists.
    @var __list: The list stored
    @var __currentIndex: Current index used in nextRotation
    """
    
    __list = [];
    __currentIndex = 0;
    
    def __init__(self,list):
        """
        @param list: Either [] or a list of rotations - [ [phi,psi,theta],  [phi,psi,theta], [phi,psi,theta] ,...]
        """
        self.__list = list; 
die eine liste speichert.

Will ich nun eine liste von angle listen initialisieren mit

Code: Alles auswählen

classRotations = [AngleList()  for _ in xrange(10)];
so wuerde

Code: Alles auswählen

classRotations[0].__list 
auf das selbe list objekt zeigen wie

Code: Alles auswählen

classRotations[1].__list 
usw.

Das Problem aussert sich durch die append funktion.
Haenge ich an classRotations[0].__list was an, so erscheint es in allen anderen.

Loesung -

Code: Alles auswählen

classRotations = [AngleList([])  for _ in xrange(10)];
Gebe neues listen objekt in die init funktion mit, welches dem __list attribut zugewiesen wird. dann unterscheiden sich alle listen voneinandern.

Kann mir jemand die Ursache zu dem Problem nennen?

Viellen Dank,
Thomas


ps: das problem hatte ich schon oeffter, deswegen interessiert es mich dringend... ist es ein Feature von Python oder eher ein Fehler?

:K
sma
User
Beiträge: 3018
Registriert: Montag 19. November 2007, 19:57
Wohnort: Kiel

Erstes: Weg mit den ";". Zweitens: Weg mit den "__" vor den Attributen. Drittens: "list" ist in schlechter Name, da er die gleichnamige eingebaute Funktion überschattet. Nimm lieber "rotations", schließlich dokumentierst du die Liste ja genau als das.

Dein Problem: Dir ist nicht klar, dass die in der Klasse definierten Attribute auch Attribute der Klasse sind und nicht der Exemplare dieser Klasse. Du kannst es so sehen, dass sich alle Exemplare diese Attribute teilen. Daher benutzt du dann jedes mal die *selbe* Liste.

Alternative:

Code: Alles auswählen

class AngleList(AngleObject):
    def __init__(self, rotations=None):
        self.rotations = rotations or []
Beachte: `__init__(self, rotations = [])` wäre falsch, denn auch das Standardargument würde unter allen Exemplaren geteilt werden.

Stefan
thomas15
User
Beiträge: 98
Registriert: Montag 7. April 2008, 19:07

Erstes: Weg mit den ";".
Neee, dat mach isch so!
Zweitens: Weg mit den "__" vor den Attributen. Drittens: "list" ist in schlechter Name, da er die gleichnamige eingebaute Funktion überschattet. Nimm lieber "rotations", schließlich dokumentierst du die Liste ja genau als das.
Ok, stimmt. Das mit dem ueberladen ist furchtbar unubersichtlich! Alles klar.
(Warum hast du was gegen diese __ konvention um "private" Attributes zu kennzeichnen. Hab nichts besseres als diese Kruecke im Netz gefunden. Alternativen wie man private und public in python trennen kann?)
Dein Problem: Dir ist nicht klar, dass die in der Klasse definierten Attribute auch Attribute der Klasse sind und nicht der Exemplare dieser Klasse. Du kannst es so sehen, dass sich alle Exemplare diese Attribute teilen. Daher benutzt du dann jedes mal die *selbe* Liste.

Alternative:

Code: (Python)
1
2
3
4
5

class AngleList(AngleObject):
def __init__(self, rotations=None):
self.rotations = rotations or []

Beachte: `__init__(self, rotations = [])` wäre falsch, denn auch das Standardargument würde unter allen Exemplaren geteilt werden.
Super! Viellen dank, das sieht gleich einleuchtender aus dieses None und die or abfrage.
sma
User
Beiträge: 3018
Registriert: Montag 19. November 2007, 19:57
Wohnort: Kiel

thomas15 hat geschrieben:Neee, dat mach isch so!
Lass es. Du willst Python programmieren und nicht Java oder C{++|#}.
(Warum hast du was gegen diese __ konvention um "private" Attributes zu kennzeichnen. Hab nichts besseres als diese Kruecke im Netz gefunden. Alternativen wie man private und public in python trennen kann?)
Es ist hässlich. Und in der Regel unnötig. Akzeptiere lieber, dass Attribute öffentlich sind. Du willst Python programmieren.

Si fueris Romae, Romano vivito more.

Stefan
Benutzeravatar
/me
User
Beiträge: 3555
Registriert: Donnerstag 25. Juni 2009, 14:40
Wohnort: Bonn

thomas15 hat geschrieben:
Erstes: Weg mit den ";".
Neee, dat mach isch so!
Wofür? Es ist sinnlos.
thomas15 hat geschrieben:(Warum hast du was gegen diese __ konvention um "private" Attributes zu kennzeichnen. Hab nichts besseres als diese Kruecke im Netz gefunden. Alternativen wie man private und public in python trennen kann?)
Das aus anderen Sprachen bekannte Konzept von private und public existiert in Python nicht in der Form, dass die Programmiersprache es erzwingt. Attribute oder Methoden die nicht von außerhalb der Klasse aufgerufen werden sollen beginnen per Konvention mit genau einem Unterstrich. In der Dokumentation findest du das im Kapitel über Klassen.
BlackJack

Man kann auch ``private`` als Krücke in Sprachen ansehen, die für Leute gedacht sind, die keine Dokumentation lesen, oder vorsätzlich dumme Sachen machen und vor sich selbst geschützt werden müssen. :-P
Antworten