Reputation: 677
class Cls():
def __init__(self, start):
self.value = start
class Desc():
def __get__(self, instance ,owner):
print("In Descriptor's __get__method")
return self.value
def __set__(self, instance, start):
print("In Descriptor's __set__ method")
self.value = start
value = Desc()
X = Cls('Hello')
X.value = "Hi"
Above implementation of descriptor is obscure for me. X.value and Cls.value are refering to same object and is of class str. but Cls.__dict__['value'] is descriptor object. There are two types assigned to a name 'value'.
Can somebody explain this?. What is the logic behind this particular implementation. Why Cls.value or X.value is not descriptor object. I am using python 3.3
Upvotes: 1
Views: 101
Reputation: 251373
You are confusing things by using the name value
for two things: one is an attribute of Cls
, and its value is a descriptor object. The other is an attribute of that descriptor object, and that is the one whose value is the string.
The key thing to remember is that there is only one descriptor object, shared across all instances of the class. When you do self.value = start
in your __set__
method, self
refers to the descriptor object, so you are setting a "value" attribute on the descriptor object itself, not on the Cls
instance. (If you change it to instance.value = start
instead, you will get a recursion error, since that will try to call __set__
again.)
You will see what is going on if you create multiple instances of your class:
>>> x = Cls("oops")
In Descriptor's __set__ method
>>> y = Cls("dang")
In Descriptor's __set__ method
>>> x.value
In Descriptor's __get__method
'dang'
>>> Cls.__dict__['value'].value
'dang'
Notice that creating y
changed x.value
. This is because there is only one descriptor object, and it only has one "value" attribute, so that value is shared across all instances of Cls
.
It's not clear what you're trying to achieve here, so it's hard to say how to "fix" this. Some general principles are:
self
in __get__
and __set__
unless you want to store class-level information. To store instance-specific data, you need to use instance
.property
and not write your own descriptor at all. If you "fixed" the descriptor you wrote above, it would still be useless, because it wouldn't do anything that property
doesn't already do.Upvotes: 4