Verstehen eines Python-Deskriptor-Beispiels (TypedProperty) - Python, Klasse, Deskriptor

Hier ist eine leicht modifizierte Version eines Codes, der in einem Python-Buch gefunden wurde:

class TypedProperty(object):
def __init__(self,name,type,default=None):
self.name = "_" + name
self.type = type
self.default = default if default else type()
def __get__(self,instance,cls):
return getattr(instance,self.name,self.default)
def __set__(self,instance,value):
if not isinstance(value,self.type):
raise TypeError("Must be a %s" % self.type)
setattr(instance,self.name,value)

class Foo(object):
name = TypedProperty("name",str)
num = TypedProperty("num",int,42)

f = Foo()
f.name = "blah"

Meine Frage: Warum erstellen wir Attribute in f? Im obigen Code wird TypedProperty so geschrieben, dass f.name = "blah" das Attribut "_name" in der Instanz f erzeugt.

Warum speichern Sie die Werte nicht als Attribute der Klasse TypedProperty? Folgendes habe ich mir vorgenommen:

class TypedProperty2(object):
def __init__(self, val, typ):
if not isinstance(val, typ):
raise TypeError()
self.value = val
self.typ = typ

def __get__(self, instance, owner):
return self.value

def __set__(self, instance, val):
if not isinstance(val, self.typ):
raise TypeError()
self.value = val

Ist das eine willkürliche Designentscheidung?

Antworten:

2 für die Antwort № 1

Alle Instanzen der Klasse teilen dieselbe Instanz des Deskriptors (z. TypedProperty). Also, wenn Sie den Wert auf dem speichern TypedProperty, dann alle Instanzen von Foo wird den gleichen Wert für die haben name und num Werte. Das ist gewöhnlich nicht wünschenswert (oder erwartet) für Deskriptoren.

z.B. wenn Sie das folgende Skript ausführen:

class TypedProperty2(object):
def __init__(self, val, typ):
if not isinstance(val, typ):
raise TypeError()
self.value = val
self.typ = typ

def __get__(self, instance, owner):
return self.value

def __set__(self, instance, val):
if not isinstance(val, self.typ):
raise TypeError()
self.value = val


class Foo(object):
name = TypedProperty2("name", str)

f1 = Foo()
f1.name = "blah"

f2 = Foo()
print(f2.name)
f2.name = "bar"

print(f1.name)

Sie sehen folgende Ausgabe:

blah
bar

so können wir das zunächst sehen f2 hätten f1"s Name und dann, nach dem Ändern des Namens von f2, f1 abgeholt f2"s Name.


Verwandte Fragen