Reputation: 24758
Can someone please help me understand this with an example?:
If an instance’s dictionary has an entry with the same name as a data descriptor, the data descriptor takes precedence. If an instance’s dictionary has an entry with the same name as a non-data descriptor, the dictionary entry takes precedence.
The implementation works through a precedence chain that gives data descriptors priority over instance variables, instance variables priority over non-data descriptors, and assigns lowest priority to _ getattr_() if provided.
Specifically what I don't understand is this:
How can an instance's dictionary have an entry with the same name as the descriptor. Can you please give me an example?
Also can you give me an example where data descriptors are being given priority over instance variables and instance variables priority over non-data descriptors etc?
Also in the code below I was surprised to see self.x in testclass invoking __ set __: I believe this behaviour is because of this explanation in the link above:
For objects, the machinery is in object.__ getattribute __ () which transforms b.x into type(b). __ dict __ ['x']. __ get __ (b, type(b)). Right ??
#! /usr/bin/env python
class descclass(object):
def __init__(self, value):
print "in desc init"
self.value = value
print "out of desc init"
def __get__(self, inst, insttype):
print "in desc get"
return self.value
def __set__(self,inst, val):
print "in desc set"
self.value = val
class testclass(object):
x = descclass(100)
print "desc created"
def __init__(self, val):
print "in testclass init"
self.x = val # this invokes __set__ on descriptor in x
print "out of testclass init"
if __name__ == '__main__':
t = testclass(45)
print t.x
print vars(t)
print vars(testclass)
Upvotes: 1
Views: 171
Reputation: 1121644
Descriptors are always part of the class; instances have their own attributes and normally they take precedence over any attributes on the class.
Data descriptors are simply descriptors that have both a __get__
and a __set__
method. So Python does this:
Point 3. and 4. are really the same thing; descriptors are class attributes with specific methods; so point 4 is really point 3 when there is no descriptor hooks on that attribute.
Upvotes: 1
Reputation: 280426
Here's an example.
# Not a data descriptor because it doesn't define __set__
class NonDataDescriptor(object):
def __get__(self, obj, objtype):
return 3
class Namespace(object):
# Data descriptor - defines both __get__ and __set__
@property
def foo(self):
return 3
bar = NonDataDescriptor()
x = Namespace()
x.__dict__['foo'] = 4 # We bypass the foo descriptor's __set__ here,
x.bar = 4 # but there's no bar setter, so this one goes to the dict
# x now has foo and bar descriptors and __dict__ entries
print x.foo # prints 3 - data descriptor wins over instance __dict__ entry
print x.bar # prints 4 - instance __dict__ entry wins over non-data descriptor
Upvotes: 4