I want to know that if I have class like this
class Test(object):
def __init__(self):
self.a = 20
self.b = 30
obj = Test()
When I do obj.a
, then which is called first?
__getattr__
or getattr
or lookup in __dict__['a']
and same with setattr
According to Python 2.7 docs:
object.__getattr__(self, name)
Called when an attribute lookup has not found the attribute in the usual places (i.e. it is not an instance attribute nor is it found in the class tree for self). name is the attribute name. This method should return the (computed) attribute value or raise an AttributeError exception.
It says not found in usual places. what is that usual places. I want to know when it is called
also what is the diff with this object.__getattribute__(self, name)
Can anyone give me example where all are used
It's a bit complicated. Here's the sequence of checks Python does if you request an attribute of an object.
First, Python will check if the object's class has a __getattribute__
method. If it doesn't have one defined, it will inherit object.__getattribute__
which implements the other ways of finding the attribute's values.
The next check is in the object's class's __dict__
. However, even if a value is found there, it may not be the result of the attribute lookup! Only "data descriptors" will take precedence if found here. The most common data descriptor is a property
object, which is a wrapper around a function that will be called each time an attribute is accessed. You can create a property with a decorator:
class foo(object):
@property
def myAttr(self):
return 2
In this class, myAttr
is a data descriptor. That simply means that it implements the descriptor protocol by having both __get__
and __set__
methods. A property
is a data descriptor.
If the class doesn't have anything in its __dict__
with the requested name, object.__getattribute__
searches through its base classes (following the MRO) to see if one is inherited. An inherited data descriptor works just like one in the object's class.
If a data descriptor was found, its __get__
method is called and the return value becomes the value of the attribute lookup. If an object that is not a data descriptor was found, it is held on to for a moment, but not returned just yet.
Next, the object's own __dict__
is checked for the attribute. This is where most normal member variables are found.
If the object's __dict__
didn't have anything, but the earlier search through the class (or base classes) found something other than a data descriptor, it takes next precedence. An ordinary class variable will be simply returned, but "non-data descriptors" will get a little more processing.
A non-data descriptor is an object with a __get__
method, but no __set__
method. The most common kinds of non-data descriptors are functions, which become bound methods when accessed as a non-data descriptor from an object (this is how Python can pass the object as the first argument automatically). The descriptor's __get__
method will be called and it's return value will be the result of the attribute lookup.
Finally, if none of the previous checks succeeded, __getattr__
will be called, if it exists.
Here are some classes that use steadily increasing priority attribute access mechanisms to override the behavior of their parent class:
class O1(object):
def __getattr__(self, name):
return "__getattr__ has the lowest priority to find {}".format(name)
class O2(O1):
var = "Class variables and non-data descriptors are low priority"
def method(self): # functions are non-data descriptors
return self.var
class O3(O2):
def __init__(self):
self.var = "instance variables have medium priority"
self.method = lambda: self.var # doesn't recieve self as arg
class O4(O3):
@property # this decorator makes this instancevar into a data descriptor
def var(self):
return "Data descriptors (such as properties) are high priority"
@var.setter # I'll let O3's constructor set a value in __dict__
def var(self, value):
self.__dict__["var"] = value # but I know it will be ignored
class O5(O4):
def __getattribute__(self, name):
if name in ("magic", "method", "__dict__"): # for a few names
return super(O5, self).__getattribute__(name) # use normal access
return "__getattribute__ has the highest priority for {}".format(name)
And, a demonstration of the classes in action:
O1 (__getattr__
):
>>> o1 = O1()
>>> o1.var
'__getattr__ has the lowest priority to find var'
O2 (class variables and non-data descriptors):
>>> o2 = O2()
>>> o2.var
'Class variables and non-data descriptors are low priority'
>>> o2.method
<bound method O2.method of <__main__.O2 object at 0x000000000338CD30>>
>>> o2.method()
'Class variables and non-data descriptors are low priority'
O3 (instance variables, including a locally overridden method):
>>> o3 = O3()
>>> o3.method
<function O3.__init__.<locals>.<lambda> at 0x00000000034AAEA0>
>>> o3.method()
'instance variables have medium priority'
>>> o3.var
'instance variables have medium priority'
O4 (data descriptors, using the property
decorator):
>>> o4 = O4()
>>> o4.method()
'Data descriptors (such as properties) are high priority'
>>> o4.var
'Data descriptors (such as properties) are high priority'
>>> o4.__dict__["var"]
'instance variables have medium priority'
O5 (__getattribute__
):
>>> o5 = O5()
>>> o5.method
<function O3.__init__.<locals>.<lambda> at 0x0000000003428EA0>
>>> o5.method()
'__getattribute__ has the highest priority for var'
>>> o5.__dict__["var"]
'instance variables have medium priority'
>>> o5.magic
'__getattr__ has the lowest priority to find magic'
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With