检查一个函数是否是某个对象的方法

22 投票
3 回答
15502 浏览
提问于 2025-04-16 17:26

如何检查一个函数是否是某个对象的方法?

举个例子:

def check_method(f):
    ...

check_method(lambda x: x + 1)           # >>> False
check_method(SomeClass().some_method)  # >>> True

在我的“你好,世界”例子中,方法有一些特殊的属性(比如 'im_self'、'__self__' 等等)。我可以依赖这些属性吗?或者有没有更好的方法呢?

3 个回答

3
>>> bstr = b'spam'
>>> str = 'eggs'
>>> hasmethod(str, 'decode')
False
>>> hasmethod(bstr, 'decode')
True

这个问题有个小变化,就是想检查某个函数的名字是否可以作为一个方法使用。由于鸭子类型在Python中很常见,所以应该有个简单的方法来实现。

hasmethod(obj, 'some_method')

但看起来并没有。

鸭子类型的最佳实践似乎就是直接尝试一下:

try:
  obj.some_method()
except:
  # try something else

如果有人想要一个函数来检查一个对象是否有某个特定名字的方法,可以使用下面提到的这个函数:

def hasmethod(obj, method_name):
  return hasattr(obj, method_name) and callable(getattr(obj, method_name))

不过在Python 3和3.1中,你需要得到callable()这个功能,但它已经被移除了。关于想要恢复这个功能的讨论可以在这个Python的bug条目中找到。

可以用以下方式恢复callable功能:

def callable(obj):
    return isinstance(obj, collections.Callable) 

这段代码直接来自上面提到的Python bug跟踪器。

其他StackOverflow上的资料提到:

callable = lambda o: hasattr(o, '__call__') or isinstance(o, collections.Callable)

这个方法在调用时添加了hasattr的检查。

在我的使用案例中,这两种方法都很好用。

想了解更多细节,可以查看之前提到的其他问题

7

你也可以检查一下在内置的类型库中定义的类型:

import types
isinstance(obj.method, types.MethodType) # True
27

使用 inspect.ismethod()

文档中说:

如果这个对象是一个在Python中定义的绑定方法,就返回真。

这意味着对于你自己在Python中定义的类,它会按照你的想法正常工作。不过,对于像 list 这样的内置类或者在扩展模块中实现的类,它会返回 False

撰写回答