[Python] Functions, Methods & Attributes!
First, lets take a look at functions & methods and then define attributes for them.
Functions Vs Methods:
In [2]: def f():
...: pass
...:
In [3]: class C:
...: def m(self):
...: pass
...:We have just defined a function and a class(with a method in it).
In [18]: type(f)
Out[18]: function
In [19]: type(C.m)
Out[19]: function
In [20]: type(C().m)
Out[20]: method
In [21]: set(dir(C().m)) - set(dir(f))
Out[21]: {'__func__', '__self__'}
As seen above, a function binded to an instance of a class is method and an unbound method is a just a function. Also a method has
__self__ and __func__ attributes in addition attributes of a function.Attributes:
Lets add some attributes to function & method and see how they work.
In [21]: setattr(f, 'state', 1)
In [22]: hasattr(f, 'state')
Out[22]: True
In [24]: getattr(f, 'state')
Out[24]: 1We can do the same thing with unbound method(which is nothing but a function) also
In [31]: setattr(C.m, 'state', 2)
In [32]: hasattr(C.m, 'state')
Out[32]: True
In [33]: getattr(C.m, 'state')
Out[33]: 2But we cant do the same thing with bound methods.
In [34]: setattr(C().m, 'state', 3)
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-34-1379e94f2f48> in <module>()
----> 1 setattr(C().m, 'state', 2)
AttributeError: 'method' object has no attribute 'state'When users add attributes to a function, they are stored in its
__dict__ attribute.In [40]: f.__dict__
Out[40]: {'state': 1}
In [49]: C.m.__dict__
Out[49]: {'state': 2}
As we have seen in the beginning, method objects just hold reference to its class(
__self__) and function(__func__). But they don't have its own __dict__ to hold custom attributes. So we cannot set custom attributes to instance methods.But we can get the function that is referenced by bound method and set attribute for it.
In [36]: setattr(C().m.__func__, 'state', 3)
In [39]: getattr(C().m.__func__, 'state')
Out[39]: 3Also methods provide, special
__getattr__ which forwards attribute access to function object. So, this will workIn [52]: hasattr(C().m, 'state')
Out[52]: True
In [53]: getattr(C().m, 'state')
Out[53]: 3
So we can just set attributes to functions & unbound methods just like classes but we can't do it for bound methods.
Need further help with this? Feel free to send a message.