Reputation: 157
Here is a slightly modified version of some code found in a python book:
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'
My question: why are we creating attributes in f? In the code above, TypedProperty is written such that f.name = 'blah' creates the attribute "_name" in the instance f.
Why not save the values as attributes of the class TypedProperty? Here is what I had in mind:
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
Is this an arbitrary design decision?
Upvotes: 2
Views: 171
Reputation: 309891
All instances of the class will share the same instance of the descriptor (e.g. TypedProperty
). So, if you store the value on the TypedProperty
, then all instances of Foo
will have the same value for the name
and num
values. This is usually not desirable (or expected) for descriptors.
e.g. if you run the following script:
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)
You'll see the following output:
blah
bar
so we can see that initially f2
had f1
's name and then, after changing the name of f2
, f1
picked up f2
's name.
Upvotes: 2