Python 使用getattr获取方法的对象引用

Python 使用getattr获取方法的对象引用,python,function,object,reference,getattr,Python,Function,Object,Reference,Getattr,比如说,我有一个名为的类名为测试,方法是名为开始 >>> class Test: ... def __init__(self, *args, **kwargs): ... pass ... def start(self): ... pass ... 现在,我有一个独立的函数,名为func >>> def func(): ... print 'this is a func and not a metho

比如说,我有一个名为
名为
测试
,方法是
名为
开始

>>> class Test:
...     def __init__(self, *args, **kwargs):
...         pass
...     def start(self):
...         pass
... 
现在,我有一个独立的
函数
,名为
func

>>> def func():
...     print 'this is a func and not a method!!!'
... 
>>> 
[1] 现在,
t.start
是属于
0xb769678c

>>> t = Test()
>>> t.start
<bound method Test.start of <__main__.Test instance at 0xb769678c>>
>>> 
现在,我们可以使用内置的
\uu模块从
t.start
func
中提取
\uu模块。毫不奇怪,
func
t.start
属于同一个
模块
,即
\uu main\uu

>>> func.__module__
'__main__'
>>> t.__module__
'__main__'
>>> 
[3] 现在,让我们在变量
obj

>>> obj = __import__(t.start.__module__)
>>> obj
<module '__main__' (built-in)>
>>> 
问题: 如何使用
getattr()
和模块名[3]获取
Test.start的句柄,该句柄应为

当我尝试在
't.start'
上使用
getattr()
时,我得到了以下
回溯

>>> 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'
>>> 
打印getattr(对象“Test.start”) 回溯(最近一次呼叫最后一次): 文件“”,第1行,在 AttributeError:“模块”对象没有属性“Test.start” >>> >>> >>>打印getattr(uuu导入(“uuu main”),“Test.start”) 回溯(最近一次呼叫最后一次): 文件“”,第1行,在 AttributeError:“模块”对象没有属性“Test.start” >>>
换句话说,我有两个数据。是的

  • \uuuu导入(“\uuuu main””)
  • sting
    'Test.start'
  • 现在,如何获取
    t.start
    的句柄(注意这里的
    实例
    ),它应该是

    我不确定您是否直接从模块中需要它(或者即使这是可能的):/

    您还可以使用:

    obj = __import__(t.start.__module__)
    
    print obj.__dict__["Test"].__dict__["start"]
    

    但是你问的是
    getattr()
    所以…

    我不确定我是否理解你的问题,但我想这正是你想要的:

    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
    
    输出:


    我想知道你为什么要写
    obj=\uuuu导入(t.start.\uu模块)

    我认为应该为主模块保留一个名称,以便能够通过getattr()函数获得模块名称空间中的对象作为模块的属性

    我告诉你,你不必做这个把戏。 globals()是表示主空间的全局命名空间的字典。 然后您可以编写,例如,
    globals()[“func”]
    来获取对象func

    我还通知您,除了使用
    getattr(N,“xyz”)
    之外,还有另一种方法可以在对象N的名称空间中获得对象xyz,因为它的名称
    xyz
    , 它是通过
    \uuuu dict\uuuu
    方法实现的:
    N.\uuuu dict\uuuu
    允许访问对象的命名空间N


    我想知道您的问题是否在于Python的微妙之处,它导致您出错

    在你的问题中,你在一个地方写了
    t.\uuuuu模块
    ,在另一个地方写了
    t.start.\uuuuu模块

    对于这两种情况,结果相同且等于
    “\uuuuu main\uuuuu”

    然而,
    1) t没有name
    \uuuu模块的属性
    2) t甚至没有name
    start
    属性
    如果您打印
    t.\uuuu dict\uuuu
    您将看到结果是
    {}

    start实际上不属于实例的命名空间t,因为它实际上属于Test的命名空间

    以下代码证明了这些确认:

    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>}
    
    * 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}
    
    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>
    
    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
    
    我的意思是Python回答说,名为
    “start”
    t属性是Test.start,而不是t.start

    因此,从
    t.start.\uuuu module\uuuu
    “\uu main\uuuu”
    这一事实来看,在我看来,您可能认为t.start属于模块名称空间,因此您应该能够编写类似于
    getattr(obj,“func”)
    的东西来获取对象start

    但这是错误的。
    在模块的全局名称空间=名称空间中找不到方法start(我编写该方法),因为它位于Test的名称空间中。作为一种方法,您必须通过实例、类或类本身来实现它


    还有一件事。
    我对方法进行了精确分析,因为我相信方法t.start基于一个函数,该函数与它不同,并且位于模块的名称空间中。实际上,方法是指向实例和此全局命名空间函数的指针包装器:

    如果您仍然不了解方法的工作原理,请查看 实施或许可以澄清问题。当一个实例属性 如果引用的不是数据属性,则将搜索其类。如果 名称表示一个有效的类属性,它是一个函数对象,一个 方法对象是通过打包(指向)实例对象而创建的 和函数对象一起出现在一个抽象对象中: 这是方法对象。当使用 参数列表,从实例构造一个新的参数列表 对象和参数列表,并使用 这是一个新的参数列表

    我想强调的是,似乎有一个函数(不是方法)存在于某个地方,方法就是基于这个函数的

    我认为这个函数位于模块名称空间中,这就是为什么
    Test.\uu dict\uuu[“start”]

    给出


    getattr(Tes)
    
    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>>
    
    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}
    
    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>
    
    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