質問

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>>

役に立ちましたか?

解決

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>>

他のヒント

obj = __import__(t.start.__module__)    

test_class = getattr(obj, 'Test')

print getattr(test_class, 'start')

I'm not sure if you need it straight from the module (or even if that is possible) :/

You could also use:

obj = __import__(t.start.__module__)

print obj.__dict__["Test"].__dict__["start"]

but you asked for getattr() so...

I wondered why you wrote obj = __import__(t.start.__module__)
I think it's to hold a name for the main module, in order to have the possibility to obtain the objects in the module's namespace as attributes of the module thanks to the getattr( ) function.

I inform you that you don't have to do this trick. globals( ) is a dictionary that represents the global namespace of the main space. Then you can write, for example, globals()["func"] to obtain the object func

I also inform you that there is another way than with getattr(N,"xyz") to obtain an object xyz in the namespace of the object N thanks to its name xyz , it's by the __dict__ method: N.__dict__ gives access to the namespace of the object N


I wonder if your problem doesn't lies in a subtlety of Python that induced you in an error.

In your question, at a place you wrote t.__module__ and at another place you wrote t.start.__module__ .
For the two cases, the result is the same and equal to "__main__"

However,
1) t has no attribute of name __module__
2) t has even no attribute of name start !
If you print t.__dict__ you'll see the result is { } !

start isn't really belonging to the namespace of the instance t because it belongs in fact to the namespace of Test

The following code proves these affirmations:

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

y = Test()
y.ku = 102

print 'y.__dict__',y.__dict__
print 'Test.__dict__',Test.__dict__

result

y.__dict__ {'ku': 102}
Test.__dict__ {'start': <function start at 0x011E11B0>,
'__module__': '__main__',
'__doc__': None,
'__init__': <function __init__ at 0x011E1170>}

.

The reason why the expressions t.__module__ and t.start.__module__ give answers anyway is explained by this citation:

A class instance has a namespace implemented as a dictionary which is the first place in which attribute references are searched.
When an attribute is not found there, and the instance’s class has an attribute by that name, the search continues with the class attributes.

http://docs.python.org/2/reference/datamodel.html#index-55

Hence:
1) t has no attribute of name __module__ then Python searches for it in the class of t
2) t has no attribute of name start then Python searches for it in the class of t

.

Well, so, Python goes to the class of t to find the values of t.__module__ and t.start.__module__
This mechanism, described by the above citation, can be observed with the following code:

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

t = Test()

print 'getattr(t,"start")'
print getattr(t,"start")

# result is
getattr(t,"start")
<bound method Test.start of <__main__.Test instance at 0x011DF288>>

I mean that Python answers that the attribute of t whose name is "start" is Test.start , not t.start !

.

Thereby, from the fact that t.start.__module__ is "__main__", it seems to me that you may have believed that t.start is belonging to the module namespace, and hence you should be able to write something similar to getattr(obj,"func") to obtain the object start

But it is false.
You can't find the method start (I write the METHOD) in the global namespace = namespace of the module, since it is in the namespace of Test. You must attain it, as a method, through the instance or the class or through the class itself.


One more thing.
I precised : the METHOD, because I believe that the method t.start is based on a FUNCTION that is something different from it and that lies in the module's namespace. In reality, a method is a wrapper of pointers pointing to an instance and to this global namespace's function:

If you still don’t understand how methods work, a look at the implementation can perhaps clarify matters. When an instance attribute is referenced that isn’t a data attribute, its class is searched. If the name denotes a valid class attribute that is a function object, a method object is created by packing (pointers to) the instance object and the function object just found together in an abstract object: this is the method object. When the method object is called with an argument list, a new argument list is constructed from the instance object and the argument list, and the function object is called with this new argument list.

http://docs.python.org/2/tutorial/classes.html#method-objects

Well what I want to underline is that it seems a function (not a method) exists somewhere, on which a method is based.

What I believe is that this function lies in the module namespace and that it's why Test.__dict__["start"]
gives
<function start at 0x011E40F0>
while
getattr(Test,"start")
and getattr(t,"start")
give
<unbound method Test.start>
and <bound method Test.start of <__main__.Test instance at 0x011DF530>>
without localizing the bound and unbound methods.

So, in my opinion, as far as I have correctly understood the doc (which is not explaining these points very well, I find, by the way) a method is a wrapper, and is based on a real function that lies in the module namespace, and that's why t.start.__module__ and Test.start.__module__ are "__main__"

It may seem a little weird that there exists a function in the module namespace that doesn't appear among the attributes of the module when we print them with globals() :

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()

print '* globals()["func"]'
print globals()["func"]
print id(globals()["func"])
print "===================================="
print '* Test.__dict__["start"]'
print Test.__dict__["start"]
print id(Test.__dict__["start"])
print '----------------------------------------------'
print '* getattr(Test,"start")'
print getattr(Test,"start")
print id(getattr(Test,"start"))
print '----------------------------------------------'
print '* getattr(t,"start")'
print getattr(t,"start")
print id(getattr(t,"start"))
print "===================================="
print globals()

result

* globals()["func"]
<function func at 0x011C27B0>
18622384
====================================
* Test.__dict__["start"]
<function start at 0x011DEFB0>
18739120
----------------------------------------------
* getattr(Test,"start")
<unbound method Test.start>
18725304
----------------------------------------------
* getattr(t,"start")
<bound method Test.start of <__main__.Test instance at 0x011DF418>>
18725304

{'__builtins__': <module '__builtin__' (built-in)>,
'__package__': None,
't': <__main__.Test instance at 0x011DF418>,
'func': <function func at 0x011C27B0>,
'Test': <class __main__.Test at 0x011DC538>,
'__name__': '__main__',
'__doc__': None}

But the fact is that we indeed see a Test.__dict__["start"] function whose address 18739120 is different from the bound and unbound methods address 18725304.
Moreover, I don't see which other explanation could explain the totality of the facts exposed.

There's in fact nothing weird in the fact that a function that didn't receive any assigned name doesn't appear in the module namespace.
It is an internal function, necessary to Python, not at the disposal of the programmer, that's all.


Concerning func, using all the methods you employed:

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()
print 'func --->',func
print id(func)

print '\nobj = __import__(t.start.__module__)  done\n'
obj = __import__(t.start.__module__)

print '* globals()["func"]'
print globals()["func"]
print id(globals()["func"])
print '* obj.__dict__["func"]'
print obj.__dict__["func"] 
print "* getattr(obj, 'func')"
print getattr(obj, 'func')
print "* getattr(__import__('__main__'), 'func')"
print getattr(__import__('__main__'), 'func')

result

func ---> <function func at 0x011C2470>
18621552

obj = __import__(t.start.__module__)  done

* globals()["func"]
<function func at 0x011C2470> # <== address in hexadecimal
18621552                      # <== address in decimal
* obj.__dict__["func"]
<function func at 0x011C2470>
* getattr(obj, 'func')
<function func at 0x011C2470>
* getattr(__import__('__main__'), 'func')
<function func at 0x011C2470>

.

Now taking apart your methods using obj :

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

print 'Test.start -->',Test.start
print id(Test.start)
print '----------------------------------------------'
print '* Test.__dict__["start"]'
print Test.__dict__["start"]
print id(Test.__dict__["start"])

print '* getattr(Test,"start")'
print getattr(Test,"start")
print id(getattr(Test,"start"))
print '\n'


print 't.start -->',t.start
print id(t.start)
print '----------------------------------------------'
print '* t.__dict__["start"]'
try:
    print t.__dict__["start"]
    print id(t.__dict__["start"])
except KeyError as e:
    print 'KeyError :',e

print '* getattr(t,"start")'
print getattr(t,"start")
print id(getattr(t,"start"))

result

Test.start --> <unbound method Test.start>
18725264
----------------------------------------------
* Test.__dict__["start"]
<function start at 0x011E40F0>
18759920
* getattr(Test,"start")
<unbound method Test.start>
18725264


t.start --> <bound method Test.start of <__main__.Test instance at 0x011DB940>>
18725264
----------------------------------------------
* t.__dict__["start"]
KeyError : 'start'
* getattr(t,"start")
<bound method Test.start of <__main__.Test instance at 0x011DB940>>
18725264

Until now, I had seldom used getattr( ).

I realize on these results that getattr( ) gives results in a specific manner: the attribute start is described as a method, bound or unbound according if it is attained through an instance or through a class.

However, only __dict__ gives precise information on the real attributes of an object.
Thus, we see that start isn't really in the namespace of the instance, but only in the namespace of the class.
It is described as being a function when it is as element of the namespace Test.__dict__ and as being a method when given as an attribute through getattr( ). There are no addresses given in this last case.

The use of the vars( ) function gives the same results.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top