【问题标题】:How to distinguish between a function and a class method?如何区分函数和类方法?
【发布时间】:2010-10-16 06:59:31
【问题描述】:

如果变量引用函数或类方法,我如何找出它是哪一个并获取类类型,以防它是类方法,特别是当类仍如给定示例中那样声明时.

例如。

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 提到的一点,我希望能够在类中声明函数时区分它(当我得到的类型是函数而不是绑定或未绑定方法时)。 IE。第一次调用get_info(__init__) 的地方我希望能够检测到它的方法被声明为类的一部分。

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

【问题讨论】:

  • 装饰器没有理由同时适用于未绑定的函数和方法函数。你为什么要这样做?为什么没有两个装饰器?

标签: python reflection metaprogramming


【解决方案1】:

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

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

【讨论】:

  • 值得一提的是,"" 是types.MethodType 类(isinstance(Foo.__init__, types.MethodType) == True)的(有些不一致的)字符串表示。
  • 顺便说一句,isinstance(bar, types.UnboundMethodType) 是假的
  • 另外,使用isinstance(...)无法区分Foo.__init__(未绑定方法)和Foo().__init__(绑定方法)。您应该检查im_self (__self__ 2.6+) 属性。
【解决方案2】:

在您调用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>

【讨论】:

    【解决方案3】:

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

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

    你不能。 J.F. Sebastian 的回答仍然 100% 适用。当类定义的主体被执行时,类本身还不存在。语句(__init__ 函数定义和get_info(__init__) 调用)发生在新的本地命名空间中;在调用get_info 时,__init__ 是对该命名空间中函数的引用,这与在类之外定义的函数没有区别。

    【讨论】:

      猜你喜欢
      • 2012-11-25
      • 2017-05-06
      • 1970-01-01
      • 2015-10-06
      • 2013-11-25
      • 2015-11-03
      • 1970-01-01
      • 1970-01-01
      • 2017-10-30
      相关资源
      最近更新 更多