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.