检查一个函数是否是某个对象的方法
如何检查一个函数是否是某个对象的方法?
举个例子:
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
文档中说:
如果这个对象是一个在Python中定义的绑定方法,就返回真。
这意味着对于你自己在Python中定义的类,它会按照你的想法正常工作。不过,对于像 list
这样的内置类或者在扩展模块中实现的类,它会返回 False
。