python: how to acces attributes of functions

Question!

I'm trying to acces attributes of member functions, but I cannot understand why I can access only through the __dict__.

class A(object):
    def fA(self):
        print A.fA.x 
    fA.x = 2

A.fA.__dict__['x'] = 3 
#A.fa.x #AttributeError: 'instancemethod' object has no attribute 'x'
A.fA.x = 4 

Why I do get an AttributeError if I try to access 'directly'?

By : jimifiki


Answers
Because of how instancemethod objects are implemented. They use a non-standard attribute-getter which doesn't allow access to non-standard attributes.

By : Amber


Not sure why you'd ever do this, but...

A.fA is actually a completely separate object vs the function fA. Watch:

>>> class A(object):
...   def fA(self): pass
...   print fA
... 
<function fA at 0x10f1c2a28>
>>> A.fA
<unbound method A.fA>

As you can see, A.fA is an "unbound method", not a function. "Unbound" means that it's not associated with any instance; whereas, bound methods are tied to a specific instance. Observe:

>>> A().fA
<bound method A.fA of <__main__.A object at 0x10f1d3d10>>

Either way, methods wrap the functions that implement them:

>>> A.fA.im_func
<function fA at 0x10f1c2a28>

Notice that the address is the same as the one printed earlier.

Strangely, I cannot repro the behavior you see:

>>> A.fA.__dict__['x'] = 1
>>> A.fA.x
1

Perhaps, this difference is due to different versions of python. Here's mine:

$ python
Python 2.7.2 (default, Jun 20 2012, 16:23:33) 
[GCC 4.2.1 Compatible Apple Clang 4.0 (tags/Apple/clang-418.0.60)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> 

PS: A.fA.x seems to work for me just as well as A.fA.im_func.x, which surprises me... Again, I'm a little suspicious about why you are thinking about doing this. Typically, the only time you'd use __dict__ is if you were implementing __getattr__ (not to be confused with __getattribute__).

It's also rare that giving objects (esp those of fundamental types) ad-hoc attributes is a good idea. An alternative that's usually viable is to use your own map e.g.

>>> def foo(): pass
... 
>>> my_x_values = {foo: 'X'}
>>> my_x_values[foo]
'X'

Not everyone agrees about this though. Check out this other SO question: Python function attributes - uses and abuses



This video can help you solving your question :)
By: admin