Antworten:
Eigenschaften sind eine besondere Art von Attribut. Grundsätzlich, wenn Python auf folgenden Code stößt:
spam = SomeObject()
print(spam.eggs)
es schaut nach oben eggsin spamund prüft dann , eggsum zu sehen , ob es einen hat __get__, __set__oder __delete__Verfahren - wenn es funktioniert, ist es eine Eigenschaft ist. Wenn es sich um eine Eigenschaft handelt, wird anstelle nur des eggsObjekts (wie bei jedem anderen Attribut) die __get__Methode aufgerufen (da wir nachgeschlagen haben) und alles zurückgegeben, was diese Methode zurückgibt.
Weitere Informationen zum Datenmodell und zu den Deskriptoren von Python .
Mit einer Eigenschaft haben Sie die vollständige Kontrolle über ihre Getter-, Setter- und Deleter-Methoden, die Sie nicht (wenn Sie keine Einschränkungen verwenden) mit einem Attribut haben.
class A(object):
_x = 0
'''A._x is an attribute'''
@property
def x(self):
'''
A.x is a property
This is the getter method
'''
return self._x
@x.setter
def x(self, value):
"""
This is the setter method
where I can check it's not assigned a value < 0
"""
if value < 0:
raise ValueError("Must be >= 0")
self._x = value
>>> a = A()
>>> a._x = -1
>>> a.x = -1
Traceback (most recent call last):
File "ex.py", line 15, in <module>
a.x = -1
File "ex.py", line 9, in x
raise ValueError("Must be >= 0")
ValueError: Must be >= 0
x. Einweg. Wenn der Benutzer der Klasse von _x erfährt, verwendet er es auf eigenes Risiko.
Im Allgemeinen sind eine Eigenschaft und ein Attribut dasselbe. In Python gibt es jedoch einen Eigenschaftsdekorator, der Getter / Setter-Zugriff auf ein Attribut (oder andere Daten) ermöglicht.
class MyObject(object):
# This is a normal attribute
foo = 1
@property
def bar(self):
return self.foo
@bar.setter
def bar(self, value):
self.foo = value
obj = MyObject()
assert obj.foo == 1
assert obj.bar == obj.foo
obj.bar = 2
assert obj.foo == 2
assert obj.bar == obj.foo
Mit der Eigenschaft können Sie Werte wie normale Attribute abrufen und festlegen. Darunter befindet sich jedoch eine Methode, die aufgerufen wird, um sie in einen Getter und Setter für Sie zu übersetzen. Es ist wirklich nur eine Annehmlichkeit, die Kesselplatte von Calling Getter und Setter zu reduzieren.
Nehmen wir zum Beispiel an, Sie hatten eine Klasse, die einige x- und y-Koordinaten für etwas enthielt, das Sie brauchten. Um sie einzustellen, möchten Sie vielleicht etwas tun wie:
myObj.x = 5
myObj.y = 10
Das ist viel einfacher zu betrachten und zu überlegen als zu schreiben:
myObj.setX(5)
myObj.setY(10)
Das Problem ist, was ist, wenn sich Ihre Klasse eines Tages so ändert, dass Sie Ihr x und y um einen Wert versetzen müssen? Jetzt müssten Sie Ihre Klassendefinition und den gesamten Code, der sie aufruft, ändern, was sehr zeitaufwändig und fehleranfällig sein kann. Mit dieser Eigenschaft können Sie die erstere Syntax verwenden und gleichzeitig die Flexibilität der Änderung der letzteren erhalten.
In Python können Sie mit der Eigenschaftsfunktion Getter, Setter und Löschmethoden definieren. Wenn Sie nur die Eigenschaft read möchten, können Sie über Ihrer Methode auch einen @ property-Dekorator hinzufügen.
Zusammenfassend habe ich 2 Unterschiede zum Standort von Bernd Klein gelernt :
1. Eigenschaft ist eine bequemere Methode zur Datenkapselung.
Beispiel: Wenn Sie ein öffentliches Attribut mit der Länge "Objekt" haben, müssen Sie es später in Ihrem Projekt kapseln, dh: es in "privat" ändern und Getter und Setter bereitstellen => Sie müssen viele der zuvor geschriebenen Codes ändern:
#Old codes
obj1.length=obj1.length+obj2.length
#New codes(Using private attibutes and getter and setter)
obj1.set_lenght(obj1.get_length()+obj2.get_length()) #=> this is ugly
Wenn Sie @property und @ lenght.setter => verwenden, müssen Sie diese alten Codes nicht ändern
2. Eine Eigenschaft kann mehrere Attribute kapseln
class Person:
def __init__(self, name, physic_health, mental_health):
self.name=name
self.__physic_health=physic_health #physic_health is real value in range [0, 5.0]
self.__mental_health=mental_health #mental_health is real value in range [0, 5.0]
@property
def condition(self):
health=self.__physic_health+self.__mental_health
if(health<5.0):
return "I feel bad!"
elif health<8.0:
return "I am ok!"
else:
return "Great!"
In diesem Beispiel __physic_healthund __mental_healthprivat ist und nicht direkt von außerhalb Seite zugegriffen werden kann, ist der einzige Weg , außerhalb des Unterrichts mit ihnen interagieren Throught Eigenschaftcondition
Es gibt auch einen nicht offensichtlichen Unterschied, den ich zum Zwischenspeichern oder Aktualisieren von Daten verwende. Oft haben wir eine Funktion, die mit dem Klassenattribut verbunden ist. Zum Beispiel muss ich die Datei einmal lesen und den dem Attribut zugewiesenen Inhalt beibehalten, damit der Wert zwischengespeichert wird:
class Misc():
def __init__(self):
self.test = self.test_func()
def test_func(self):
print 'func running'
return 'func value'
cl = Misc()
print cl.test
print cl.test
Ausgabe:
func running
func value
func value
Wir haben zweimal auf das Attribut zugegriffen, aber unsere Funktion wurde nur einmal ausgelöst. Wenn Sie das obige Beispiel so ändern, dass die Eigenschaft verwendet wird, wird der Wert jedes Mal aktualisiert, wenn Sie darauf zugreifen:
class Misc():
@property
def test(self):
print 'func running'
return 'func value'
cl = Misc()
print cl.test
print cl.test
Ausgabe:
func running
func value
func running
func value