Each object has a dictionary of attributes that contains it's variables and functions. Referring to these dictionaries:
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.
This is what they were talking about.
To show this:
#data descriptor
class A(object):
def __get__(self, obj, type):
print "hello from get A"
def __set__(self, obj, val):
print "hello from set A"
#non data descriptor
class B(object):
def __get__(self, obj, type):
print "hello from get B"
class C(object):
#our data descriptor
a = A()
#our non data descriptor
b = B()
>>> c = C()
>>> c.a
hello from get A
>>> c.b
hello from get B
>>> c.a = 0
hello from set A
>>> c.a #notice after reassignment, A.__get__ is still called
hello from set A
>>> c.b = 0 #instance variable with the same name as the non data-descriptor
>>> c.b #notice how B.__get__ isn't called anymore
0
Basically it is saying that when __get__
and __set__
are user defined for an object (data descriptor), they will be called instead of the default methods. If only __get__
is user defined for an object(non-data descriptor), the instance can reassign am instance variable.
So when calling g.x = 0
: if x is a data descriptor then x's user-defined __set__
method is called, when x is an instance variable, or non-data descriptor the default behavior is called.
With a data descriptor, the class is controlling all access and modification to the variables. All access to variables of your data descriptor type will go through __get__
and __set__
. So c.a = 0
calls A.__set__
and c.a is changed how the class defined it. There is no way to create an instance variable 'c.a' that is not of the type A.
With a non data descriptor, the class only controls access, so when c.b = 0
is called, since __set__
isn't defined, a new instance variable is made(the default behavior). There is no user-defined behavior on setting the variable, so you can create an instance variable with the same name, without the __get__
behavior.
The precedence they are talking about is the dynamics of the two. A data descriptor will always call __get__
and __set__
, and so an instance variable can't be created with the same name. A non data descriptor will only call __get__
until an instance variable with the same name is created.