Frage

Also, ich spiele mit Dekorateure in Python 2.6, und ich einige Probleme, bekommen sie zu arbeiten. Hier ist meine Klassendatei:

class testDec:

    @property
    def x(self): 
        print 'called getter'
        return self._x

    @x.setter
    def x(self, value): 
        print 'called setter'
        self._x = value

Was ich dachte, das ist gemeint x wie eine Eigenschaft zu behandeln, aber diese Funktionen auf get und set rufen. So feuerte ich auf IDLE und überprüft es:

>>> from testDec import testDec
from testDec import testDec
>>> t = testDec()
t = testDec()
>>> t.x
t.x
called getter
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "testDec.py", line 18, in x
    return self._x
AttributeError: testDec instance has no attribute '_x'
>>> t.x = 5
t.x = 5
>>> t.x
t.x
5

Klar, dass der erste Aufruf funktioniert wie erwartet, da ich die Getter nennen, und es gibt keinen Standardwert, und es funktioniert nicht. OK, gut, ich verstehe. Allerdings scheint der Anruf zuweisen t.x = 5 eine neue Eigenschaft x zu schaffen, und jetzt das Getter funktioniert nicht!

Was bin ich fehlt?

War es hilfreich?

Lösung

Sie scheinen zu verwenden klassische alter Stil Klassen in python 2. um Eigenschaften korrekt arbeiten Sie verwenden müssen, new-Style-Klassen statt (in python 2 müssen Sie erben von object ). Nur Ihre Klasse als MyClass(object) deklarieren:

class testDec(object):

    @property
    def x(self): 
        print 'called getter'
        return self._x

    @x.setter
    def x(self, value): 
        print 'called setter'
        self._x = value

Es funktioniert:

>>> k = testDec()
>>> k.x
called getter
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/devel/class_test.py", line 6, in x
    return self._x
AttributeError: 'testDec' object has no attribute '_x'
>>> k.x = 5
called setter
>>> k.x
called getter
5
>>> 

Ein weiteres Detail, die Probleme verursachen könnte, ist, dass beide Methoden die gleichen Namen für die Eigenschaft arbeiten müssen. Wenn Sie die Setter mit einem anderen Namen wie folgt definieren wird es nicht funktionieren :

@x.setter
def x_setter(self, value):
    ...

Und noch eine Sache, die anfangs nicht ganz leicht zu erkennen ist, ist die Reihenfolge: Der Getter muss zuerst definiert werden . Wenn Sie die Setter zuerst definieren, erhalten Sie name 'x' is not defined Fehler.

Andere Tipps

Nur ein Hinweis für andere Leute, die hier stolpern für diese Ausnahme suchen: beide Funktionen benötigen den gleichen Namen haben. Benennen der Methoden wie folgt zu einer Ausnahme führen wird:

@property
def x(self): pass

@x.setter
def x_setter(self, value): pass

Statt beiden Methoden die gleichen Namen geben

@property
def x(self): pass

@x.setter
def x(self, value): pass

Es ist auch wichtig, dass die Reihenfolge der Erklärung Fragen zu beachten. Der Getter muss vor dem Setter in der Datei definiert werden, sonst werden Sie eine NameError: name 'x' is not defined bekommen

Sie brauchen neue Stil-Klassen verwenden, die Sie durch Ableiten der Klasse von Objekt zu tun:

class testDec(object):
   ....

Dann sollte es funktionieren.

Im Fall kommt hier jemand von Google, zusätzlich zu den oben genannten Antworten, die ich möchte hinzufügen, dass diese Aufmerksamkeit braucht, wenn die Setter aus der __init__ Methode Ihrer Klasse aufgerufen wird, basierend auf diese Antwort Im Einzelnen:

class testDec(object):                                                                                                                                            

    def __init__(self, value):
        print 'We are in __init__'
        self.x = value # Will call the setter. Note just x here
        #self._x = value # Will not call the setter

    @property
    def x(self):
        print 'called getter'
        return self._x # Note the _x here

    @x.setter
    def x(self, value): 
        print 'called setter'
        self._x = value # Note the _x here

t = testDec(17)
print t.x 

Output:
We are in __init__
called setter
called getter
17
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top