21

所以这段代码:

from inspect import *

class X(object):
  def y(self):
    pass

methods = getmembers(X, predicate=ismethod)
functions = getmembers(X, predicate=isfunction)

print("%r" % methods)
print("%r" % functions)

从 python2.7 产生:

[('y', <unbound method X.y>)]
[]

并从 python3.3 产生:

[]
[('y', <function X.y at 0x1006ee3b0>)]

我四处张望,但我看不出这种行为变化的任何明显原因。

具体来说,为什么 python 3 将我的方法视为一个函数?

是否有任何跨运行时方式来获取类上的方法列表?

(即在 python2.X 和 3.X 上运行时返回相同的东西)

编辑: getmembers() 不工作的例子:

from inspect import *

class X(object):
  def y(self):
    pass

methods = getmembers(X)
for i in methods:
  if ismethod(i):
    print("Method: %s" % str(i))
  else:
    print("Not a method: %s" % str(i))

印刷:

Not a method: ('__class__', <attribute '__class__' of 'object' objects>)
Not a method: ('__delattr__', <slot wrapper '__delattr__' of 'object' objects>)
Not a method: ('__dict__', <attribute '__dict__' of 'X' objects>)
Not a method: ('__dir__', <method '__dir__' of 'object' objects>)
Not a method: ('__doc__', None)
Not a method: ('__eq__', <slot wrapper '__eq__' of 'object' objects>)
Not a method: ('__format__', <method '__format__' of 'object' objects>)
Not a method: ('__ge__', <slot wrapper '__ge__' of 'object' objects>)
Not a method: ('__getattribute__', <slot wrapper '__getattribute__' of 'object' objects>)
Not a method: ('__gt__', <slot wrapper '__gt__' of 'object' objects>)
Not a method: ('__hash__', <slot wrapper '__hash__' of 'object' objects>)
Not a method: ('__init__', <slot wrapper '__init__' of 'object' objects>)
Not a method: ('__le__', <slot wrapper '__le__' of 'object' objects>)
Not a method: ('__lt__', <slot wrapper '__lt__' of 'object' objects>)
Not a method: ('__module__', '__main__')
Not a method: ('__ne__', <slot wrapper '__ne__' of 'object' objects>)
Not a method: ('__new__', <built-in method __new__ of type object at 0x1001e0640>)
Not a method: ('__reduce__', <method '__reduce__' of 'object' objects>)
Not a method: ('__reduce_ex__', <method '__reduce_ex__' of 'object' objects>)
Not a method: ('__repr__', <slot wrapper '__repr__' of 'object' objects>)
Not a method: ('__setattr__', <slot wrapper '__setattr__' of 'object' objects>)
Not a method: ('__sizeof__', <method '__sizeof__' of 'object' objects>)
Not a method: ('__str__', <slot wrapper '__str__' of 'object' objects>)
Not a method: ('__subclasshook__', <method '__subclasshook__' of 'object' objects>)
Not a method: ('__weakref__', <attribute '__weakref__' of 'X' objects>)
Not a method: ('y', <function X.y at 0x1006ee3b0>)
4

2 回答 2

22

与 Python 3没有特别的区别,inspect但一般请参见此处

“未绑定方法”的概念已从语言中删除。当引用一个方法作为类属性时,你现在得到一个普通的函数对象。

我对跨平台的建议是:

getmembers(X, predicate=lambda x: isfunction(x) or ismethod(x))
于 2013-06-10T08:45:02.420 回答
8

Because essentialy there is no difference between a function and an unbound method. This idea of unbound methods exists in Python 2 mostly for historical reasons and was removed in Python 3.

This email by the BDFL himself goes into some details.


Answering your updated question. I think its best to use inspect.isroutine as it matches both unbound methods and functions with an additional benefit of also matching methods/functions implemented in C.

Start with inspect.getmembers and filter its output as you need. It also takes an optional predicate parameter.

于 2013-06-10T08:45:55.703 回答