如何区分函数和类方法?

时间:2009-03-30 00:16:10

标签: python reflection metaprogramming

如果一个变量引用了一个函数或一个类方法,我怎么能找出它是哪一个并获得类类型,以防它是一个类方法,特别是当类仍然被声明为给定的例子时

例如

def get_info(function_or_method):
    print function_or_method

class Foo(object):
    def __init__(self):
        pass

    get_info(__init__)

def bar():
    pass

get_info(bar)

在David和J. F. Sebastian的前两个回复后更新问题 再次强调J.F.Sebastian提到的一个观点,我希望能够在类中声明函数时区分它(当我得到的类型是函数而不是绑定或未绑定的方法时)。即。第一次调用get_info(__init__)时,我希望能够检测到它的方法被声明为类的一部分。

这个问题出现了,因为我在它周围放了一个装饰器,它得到了 init 函数的句柄,我实际上无法弄清楚是否在类中声明了一个方法一个独立的功能

3 个答案:

答案 0 :(得分:12)

您可以通过检查类型来区分两者:

>>> type(bar)
<type 'function'>
>>> type(Foo.__init__)
<type 'instancemethod'>

>>> import types
>>> isinstance(bar, types.FunctionType)
True
>>> isinstance(bar, types.UnboundMethodType)
True

这是您在if语句中执行此操作的方式。

此外,您可以从方法的im_class属性获取该类:

>>> Foo.__init__.im_class
__main__.Foo

答案 1 :(得分:9)

当你调用get_info(__init__)时(在类定义中),__init__是一个普通的函数。

def get_info(function_or_method):
    print function_or_method

class Foo(object):
    def __init__(self):
        pass
    get_info(__init__)   # function

def bar():
    pass

get_info(Foo.__init__)   # unbound method
get_info(Foo().__init__) # bound method
get_info(bar)            # function

输出(CPython,IronPython):

<function __init__ at ...>
<unbound method Foo.__init__>
<bound method Foo.__init__ of <__main__.Foo object at ...>>
<function bar at ...>

输出(Jython):

<function __init__ 1>
<unbound method Foo.__init__>
<method Foo.__init__ of Foo instance 2>
<function bar 3>

答案 2 :(得分:4)

  

为了再次强调J.F.Sebastian提到的一个观点,我希望能够在类中声明函数时区分它(当我得到的类型是函数而不是绑定或未绑定的方法时)。即。第一次调用get_info(__init__)时,我希望能够检测到它的方法被声明为类的一部分。

     

这个问题出现了,因为我在它周围放了一个装饰器,它得到一个init函数的句柄,我实际上无法弄清楚一个方法是在类中声明还是作为一个独立的函数

你做不到。 J.F.塞巴斯蒂安的回答仍然100%适用。当正在执行类定义的主体时,类本身尚不存在。语句(__init__函数定义和get_info(__init__)调用)发生在新的本地名称空间中;在调用get_info时,__init__是对该命名空间中函数的引用,这与在类外定义的函数无法区分。