说,我有以下class
名为Test
,method
名为start
>>> class Test:
... def __init__(self, *args, **kwargs):
... pass
... def start(self):
... pass
...
现在,我有一个名为function
func
>>> def func():
... print 'this is a func and not a method!!!'
...
>>>
[1]
现在,t.start
是method
的{{1}},属于instance of __main__.Test
0xb769678c
[2]
>>> t = Test()
>>> t.start
<bound method Test.start of <__main__.Test instance at 0xb769678c>>
>>>
是func
,属于function
0xb767ec6c
现在,我们可以使用内置>>> func
<function func at 0xb767ec6c>
>>>
从__module__
和t.start
中提取func
。毫不奇怪,__module__
和func
属于同一t.start
,即module
__main__
[3]
现在,我们将>>> func.__module__
'__main__'
>>> t.__module__
'__main__'
>>>
__module__
存储在变量t.start
obj
现在,我使用>>> obj = __import__(t.start.__module__)
>>> obj
<module '__main__' (built-in)>
>>>
获取函数getattr()
的{{1}}句柄func
,如下所示<function func at 0xb767ec6c>
的输出为func
到[2]
getattr()
如何使用identical
和模块名称[3]来获取>>> print getattr(obj, 'func')
<function func at 0xb767ec6c>
>>>
>>> print getattr(__import__('__main__'), 'func')
<function func at 0xb767ec6c>
>>>
[1]的句柄getattr()
当我尝试在Test.start
上使用<bound method Test.start of <__main__.Test instance at 0xb769678c>>
时,我得到了以下getattr()
't.start'
换句话说,我有两个数据。他们是
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'
>>>
现在,如何获取__import__('__main__')
的句柄(请注意'Test.start'
此处)t.start
答案 0 :(得分:2)
我不确定我是否理解你的问题,但我认为这符合你的要求:
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
输出:
<unbound method Test.start>
<function func at 0x00BA67F0>
<bound method Test.start of <__main__.Test instance at 0x00BAC170>>
答案 1 :(得分:1)
obj = __import__(t.start.__module__)
test_class = getattr(obj, 'Test')
print getattr(test_class, 'start')
我不确定你是否需要直接从模块中获取(或者即使可能):/
你也可以使用:
obj = __import__(t.start.__module__)
print obj.__dict__["Test"].__dict__["start"]
但您要求getattr()
所以......
答案 2 :(得分:0)
我想知道你为什么写obj = __import__(t.start.__module__)
我认为为主模块保留一个名称,以便有可能获得模块命名空间中的对象作为模块的属性,这要归功于 getattr()强>功能。
我告诉你,你不必做这个伎俩。
globals()是一个字典,表示主空间的全局命名空间。
然后你可以编写globals()["func"]
来获取对象 func
我还告诉您,除了getattr(N,"xyz")
之外,还有另一种方法可以在对象 N 的命名空间中获取对象 xyz ,这要归功于其名称{ {1}},
它是xyz
方法的:
__dict__
可以访问对象 N
我想知道你的问题是否存在于Python的微妙之中,导致你出错。
在您的问题中,在您撰写N.__dict__
的地方和您撰写t.__module__
的其他地方。
对于这两种情况,结果相同并等于t.start.__module__
然而,
1) t 没有名称"__main__"
的属性
2) t 甚至没有名称__module__
的属性!
如果您打印start
,则会看到结果为t.__dict__
!
开始并非真正属于 t 实例的命名空间,因为它实际上属于测试 <的命名空间/ p>
以下代码证明了这些肯定:
{ }
结果
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__
表达式y.__dict__ {'ku': 102}
Test.__dict__ {'start': <function start at 0x011E11B0>,
'__module__': '__main__',
'__doc__': None,
'__init__': <function __init__ at 0x011E1170>}
和t.__module__
无论如何给出答案的原因可以通过以下引文解释:
类实例具有作为字典实现的名称空间 搜索属性引用的第一个地方 当一个 在那里找不到属性,并且实例的类有一个 通过该名称的属性,搜索继续该类 属性。
因此:
1) t 没有名称t.start.__module__
的属性,然后Python在 t 类中搜索它
2) t 没有名称__module__
的属性,然后Python在 t
那么,Python进入 t 类来查找start
和t.__module__
的值。
通过以上引用描述的这种机制可以用以下代码观察:
t.start.__module__
我的意思是Python回答名称为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>>
的 t 的属性为 Test.start ,而不是 t.start !
因此,从"start"
是t.start.__module__
的事实来看,在我看来,您可能认为 t.start 属于模块命名空间,因此您应该能够写出与"__main__"
类似的内容来获取对象开始
但这是假的 您无法在模块的global namespace =命名空间中找到方法 start (我编写METHOD),因为它位于 Test 的命名空间中。你必须通过实例或类或通过类本身来实现它,作为一种方法。
还有一件事。
我精确地使用了METHOD,因为我认为方法 t.start 基于 FUNCTION ,它与它不同,而位于模块中&# 39; s名称空间。实际上,方法是指向实例和指向此全局命名空间函数的指针的包装器:
如果你仍然不明白方法是如何工作的,那么看看 实施也许可以澄清问题。当一个实例属性 引用的不是数据属性,搜索其类。如果 name表示一个有效的class属性,它是一个函数对象,a 方法对象是通过打包(指向)实例对象来创建的 和一个在抽象对象中一起找到的函数对象: 这是方法对象。用方法调用方法对象时 参数列表,从实例构造一个新的参数列表 对象和参数列表,以及调用函数对象 这个新的参数列表。
http://docs.python.org/2/tutorial/classes.html#method-objects
我想要强调的是,似乎某个方法所基于的某个函数(不是方法)存在。
我认为这个功能在于模块名称空间,这就是getattr(obj,"func")
的原因。
给
Test.__dict__["start"]
而
<function start at 0x011E40F0>
和getattr(Test,"start")
给
getattr(t,"start")
和<unbound method Test.start>
没有本地化绑定和未绑定的方法。
所以,在我看来,只要我正确地理解了doc(没有很好地解释这些要点,顺便说一下,我发现)一个方法是一个包装器,它基于一个真实的位于模块命名空间中的函数,以及<bound method Test.start of <__main__.Test instance at 0x011DF530>>
和t.start.__module__
为Test.start.__module__
模块命名空间中存在一个函数似乎有点奇怪,当我们用"__main__"
打印它们时,它们不会出现在模块的属性中:
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()
但事实是我们确实看到* 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}
函数,其地址18739120与绑定和未绑定方法地址18725304不同。
此外,我不知道哪些其他解释可以解释所揭露事实的全部。
事实上,没有收到任何指定名称的函数不会出现在模块名称空间中,这一点并不奇怪。
它是一个内部函数,是Python必需的,而不是程序员可以使用的。
关于 func ,使用您使用的所有方法:
Test.__dict__["start"]
结果
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')
现在使用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>
:
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"))
到现在为止,我很少使用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
。
我在这些结果中意识到getattr( )
以特定方式给出了结果:属性 start 被描述为一种方法,如果通过实例或通过实例获得,则绑定或不绑定一堂课。
但是,只有getattr( )
才能提供有关对象真实属性的准确信息
因此,我们看到 start 并非真正位于实例的命名空间中,而是仅存在于类的命名空间中。
它被描述为当它作为命名空间__dict__
的元素时的函数,并且当通过Test.__dict__
作为属性给出时是一种方法。在最后一种情况下没有给出地址。
使用 vars()函数可以得到相同的结果。