Search code examples
pythonfunctionobjectreferencegetattr

Obtaining object reference for a method using getattr


Say, I have the following class called Test with a method called start

>>> class Test:
...     def __init__(self, *args, **kwargs):
...         pass
...     def start(self):
...         pass
... 

Now, I have a standalone independent function called func

>>> def func():
...     print 'this is a func and not a method!!!'
... 
>>> 

[1] Now, t.start is a method of an instance of __main__.Test which belong to 0xb769678c

>>> t = Test()
>>> t.start
<bound method Test.start of <__main__.Test instance at 0xb769678c>>
>>> 

[2] func is a function which belong to the location 0xb767ec6c

>>> func
<function func at 0xb767ec6c>
>>> 

Now, we can extract the __module__ from t.start and func by using builtin __module__. Not surprisingly, func and t.start belong to the same module i.e. __main__

>>> func.__module__
'__main__'
>>> t.__module__
'__main__'
>>> 

[3] Now, lets store __module__ for t.start in a variable obj

>>> obj = __import__(t.start.__module__)
>>> obj
<module '__main__' (built-in)>
>>> 

Now, I use getattr() to get the func handle <function func at 0xb767ec6c> for function func as follows and the output of getattr() is the identical to [2]

>>> print getattr(obj, 'func')
<function func at 0xb767ec6c>
>>> 
>>> print getattr(__import__('__main__'), 'func')
<function func at 0xb767ec6c>
>>> 

Question:

How do I use getattr() and the module name [3] to get the handle of Test.start [1] which should be <bound method Test.start of <__main__.Test instance at 0xb769678c>>

When I tried using getattr() on 't.start' I got the following Traceback

>>> print getattr(obj, 'Test.start')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'module' object has no attribute 'Test.start'
>>> 
>>> 
>>> print getattr(__import__('__main__'), 'Test.start')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'module' object has no attribute 'Test.start'
>>> 

In other words, I have two data with me. They are

  1. __import__('__main__')
  2. The sting 'Test.start'

Now, how do I get the handle for t.start (note the instance here) which should be <bound method Test.start of <__main__.Test instance at 0xb769678c>>


Solution

  • I'm not sure if I understand your question(s), but I think this does what you want:

    class Test:
        def __init__(self, *args, **kwargs):
            pass
        def start(self):
            pass
    
    def func():
        print('this is a func and not a method!!!')
    
    t = Test()
    
    module = __import__(t.start.__module__)
    
    print(vars(module)['Test'].start)
    print(vars(module)['func'])
    print(vars(module)['t'].start)
    

    (Python 3) output:

    <function Test.start at 0x00E52460>
    <function func at 0x00E524F0>
    <bound method Test.start of <__main__.Test object at 0x008DF670>>