Frage

ich eine Python-Klassenhierarchie habe, dass ich zur Laufzeit verlängern will. Außerdem hat jede Klasse in dieser Hierarchie ein statisches Attribut ‚dict‘, dass ich in jeder Unterklasse überschrieben werden soll. Fachter es sieht wie folgt aus:

'dict' eine geschützte (Öffentlichkeit, sondern mit führendem Unterstrich) Mitglied

class A(object):
    _dict = {}

    @classmethod
    def getdict(cls):
        return cls._dict

    @classmethod
    def setval(cls, name, val):
        cls._dict[name] = val

    @classmethod
    def addchild(cls, name):
        return type(name, (cls, ), { '_dict' : {} })

B = A.addchild('B')
A.setval(1, 5)

print A.getdict()
# prints: {1: 5}
# like expected

print B.getdict()
# prints: {}
# like expected

Dies funktioniert genauso wie erwartet. Die Frage ist nun: Warum tut es nicht mehr funktionieren, wenn ich das Attribut privat deklarieren:

Nun ist die gleiche Sache mit 'dict' ein privates Mitglied beeing

class C(object):
    __dict = {}

    @classmethod
    def getdict(cls):
        return cls.__dict

    @classmethod
    def setval(cls, name, val):
        cls.__dict[name] = val

    @classmethod
    def addchild(cls, name):
        return type(name, (cls, ), { '__dict' : {} })

D = C.addchild('D')
C.setval(1, 5)

print C.getdict()
# prints: {1: 5}
# like expected

print D.getdict()
# prints: {1: 5}
# why!?

Plötzlich D, die Unterklasse von C, hat die gleichen Werte in 'dict' als Superklasse!?

Könnte jemand so freundlich sein und mir erklären, was der Grund dafür ist? Vielen Dank im Voraus!

War es hilfreich?

Lösung

phild, wie Sie wissen, wenn Sie einen Attributnamen mit Doppelstrich __ Präfix, automagically das Python-Interpreter ändert (Mangeln) Attributnamen von __attribute zu _CLS__attribute, wo CLS ist der Klassenname.

Wenn Sie jedoch sagen

return type(name, (cls, ), { '__dict' : {} })

die Schlüssel im Wörterbuch { '__dict' : {} } verstümmelt werden nicht. __dict bleibt gleich.

So D endet mit beiden D._C__dict und D.__dict oben:

(Pdb) dir(D)
['_C__dict', '__class__', '__delattr__', '__dict', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'addchild', 'getdict', 'setval']

D._C__dict bezieht sich auf C Klasse Attribut. Also, wenn Sie laufen

C.setval(1, 5)

Sie ändern D._C__dict sowie C._C__dict. Sie sind ein und dasselbe.

Andere Tipps

Hier ist ein Kapitel in der Dokumentation über "private" Attribute . Und ich bemerkte man Klassendefinition, um es klar:

class C(object):
    __dict = {} # This creates C.__dict__['_C__dict']

    @classmethod
    def getdict(cls):
        return cls.__dict # Uses cls.__dict__['_C__dict'] 

    @classmethod
    def setval(cls, name, val):
        cls.__dict[name] = val # Uses cls.__dict__['_C__dict'] 

    @classmethod
    def addchild(cls, name):
        return type(name, (cls, ), { '__dict' : {} }) # Creates child.__dict__['__dict']

d. alle Childs haben ihr eigenes __dict Attribut, aber nur einer von Basisklasse verwendet wird.

Die Java oder C ++ Konzepte von „geschützt“ und „privaten“ nicht gelten. Die Namenskonvention Python tut ein wenig, aber nicht das, was bildest du dir.

Der __name hat einige Namen Mangeln, ist es schwer, den Zugang zu machen, weil der Name verdeckt wird.

Ihre _dict und __dict sind einfach Klasse-Level-Attribute, die von allen Instanzen der Klassen einfach geteilt werden.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top