2010-09-23 8 views
7

Was ist der Grund, die Variable die self._age zu verwenden? Ein ähnlicher Name, der nicht mit der bereits verwendeten self.age verknüpft ist?Eigenschaften in Python

class newprops(object): 
    def getage(self): 
     return 40 
    def setage(self, value): 
     self._age = value 
    age = property(getage, setage, None, None) 
+7

'return 40' - erinnert mich an Zufallszahlengenerator des xkcd! – katrielalex

Antwort

11

ist bereits von der Eigenschaft belegt, Sie müssen der tatsächlichen Variablen, die hier _age ist, einen anderen Namen geben.

BTW, da Python 2.6, könnten Sie diese mit Dekorateure schreiben:

def newprops(object): 

    @property 
    def age(self): 
     return 40 

    @age.setter 
    def age(self, value): 
     self._age = value 
+3

Die Verwendung eines Namens, der mit einem Unterstrich beginnt, hat einen weiteren Vorteil: Es ist die allgemein anerkannte Namenskonvention für "private" (= "berühre nicht, es sei denn du musst") Dinge. – delnan

+0

Und die Verwendung eines Namens, der mit einem doppelten Unterstrich beginnt, ist die allgemein anerkannte Konvention für "wirklich privat". In einem von Pythons ärgerlichen Warzen werden doppelte Unterstreichungsnamen zerfleischt, so dass du sie nicht einmal anrufen kannst, wenn du nicht selbst den Mangel hackst! – katrielalex

+0

@delnan: Ich würde eher sagen, es ist die Konvention für "geschützt", und zu vorsichtig Programmierer verwenden die Pseudo-private Name Mangling-Funktion, um "private" Variablen etwas zu simulieren. – AndiDog

0

Was Sie geschrieben haben, würde nie in Python geschrieben werden. Oftmals müssen jedoch beim Speichern einer Eigenschaft (z. B. Serialisierung) Aktionen ausgeführt werden, die transparent in einer Eigenschaft zwischengespeichert werden können.

Da das Protokoll zum Aufrufen einer Eigenschaft und zum Zugreifen auf ein Element identisch ist, muss der Python-Stil so lange wie möglich warten, um Elementvariablen in Eigenschaften umzuwandeln.

+0

"Was du geschrieben hast, würde niemals in Python geschrieben werden." Sag das Mark Lutz. Er hat es in sein Buch geschrieben! – MrMas

4

Ihr Beispiel ist eigentlich Unsinn, weil der Getter eine Konstante zurückgibt. Ein separater Unterstrich-benannte Variable in der Regel in Verbindung mit Eigenschaften, die

1) Nur-Lese-

class C(object): 
    @property 
    def age(self): 
     return self._age 

In diesem Fall sein kann, instance.age kann nur gelesen werden, aber nicht zugewiesen. Die Konvention besteht darin, intern unter self._age zu schreiben.

2) read-write

class C(object): 
    @property 
    def age(self): 
     return self._age 

    @age.setter 
    def age(self, value): 
     assert value >= 0 
     self._age = value 

Getter und Setter zu haben, macht nur Sinn, wenn Sie zusätzliche Berechnungen oder Kontrollen zu tun haben, wenn Sie den Wert zuweisen. Wenn nicht, können Sie die Variable einfach ohne den Unterstrich deklarieren, da auf Eigenschaften und Instanzvariablen in gleicher Weise (in Form von Code) zugegriffen wird. Deshalb müssen _age und die Eigenschaft age natürlich anders benannt werden.

+0

korrekt! Vielen Dank. Ich gehe durch dieses Buch, und das war das Beispiel ... Ich war wie WTF, woher kam das? – shawn

+0

Im ersten Beispiel kann 'instance.age' sicherlich zugewiesen werden. Probieren Sie 'instance.age = sqlite3.connect (': memory:')' aus. Da es kein "__set__" definiert, geht jede Zuweisung direkt in die Instanzen "__dict__" und zukünftige Versuche, auf den Deskriptor zuzugreifen, gehen direkt zu "__dict__". – aaronasterling

+0

Wenn Sie eine schreibgeschützte Eigenschaft haben möchten, definieren Sie '__set__', um' AttributeError' zu erhöhen. – aaronasterling

6

Einige objektorientierte Sprachen haben sogenannte private Attribute, auf die von außerhalb der Klassenmethoden nicht zugegriffen werden kann. Dies ist wichtig, da einige Attribute nicht direkt geändert werden sollen, sondern sie als eine Funktion von etwas anderem geändert oder validiert werden sollen, bevor sie geändert werden. In Python haben Sie keine private Attribute, aber Sie können etwas ähnliches implementieren, indem Sie Getter und Setter zu einer Variablen verwenden, die mit Unterstrich beginnt - Pythons Konvention für private Methoden und Attribute.

Zum Beispiel. Die Hypotenuse eines rechtwinkligen Dreiecks ist gegeben durch h=sqrt(a*a+b*b), so dass Sie h nicht direkt ändern können, weil die Beziehung gelten muss. Auch sagen, dass ein Name mich im Format LASTNAME COMMA FIRSTNAME haben muss, dann müssen Sie überprüfen, dass dies der Fall ist, bevor Sie self.lastname zuweisen.

Die Eigenschaft Getter ermöglicht es Ihnen, die Hypotenuse zu erhalten, verbietet Ihnen jedoch, sie festzulegen. Mit dem Eigenschaftensetter können Sie eine Eigenschaft festlegen, Sie können jedoch Prüfungen vornehmen, bevor Sie die Eigenschaft tatsächlich festlegen.

So:

class Person(object) 
def __init__(self): 
    # The actual attribute is _name 
    self._name = None 
@property 
def name(self): 
    # when I ask for the name, I mean to get _name 
    return self._name 
@name.setter 
def name(self, value): 
    # before setting name I can ensure that it has the right format 
    if regex_name.match(value): 
    # assume you have a regular expression to check for the name 
    self._name = value 
    else: 
    raise ValueError('invalid name') 

Ein weiteres Beispiel:

class Triangle(object): 
def __init__(self, a, b): 
    # here a and b do not need to be private because 
    # we can change them at will. However, you could 
    # make them private and ensure that they are floats 
    # when they are changed 
    self.a = a 
    self.b = b 
@property 
def h(self): 
    return math.sqrt(a*a+b*b) 
# notice there is no h.setter - you cannot set h directly 
+2

Große Beispiele, effektive Kommentare. – Air

Verwandte Themen