我想知道是否为类
的实例定义了一个函数class c(object):
def func(self): pass
cc = c()
>>> is_function_defined_for_instance(cc,'func')
True
>>> is_function_defined_for_instance(cc,'cnuf')
False
我对该功能最干净的尝试是:
def is_function_defined_for_instance(instance,function):
return callable(getattr(instance,function,None))
# returns True iff function is defined for class of instance (not super classes)
def is_function_defined_for_instance(instance,function):
return bool(instance.__class__.__dict__.get(function))
是否有内置或更好的方式来完成我正在寻找的东西?
答案 0 :(得分:3)
在Python 2.6或更高版本中,推荐的方法是:
import collections
def is_func(instance, func):
return isinstance(getattr(instance, func, None), collections.Callable)
collections
模块中的新ABCs(抽象基类)是正确的方法,在Python 2.6+和3.any中,执行这种“类似鸭子的类型检查” - 很多比callable
内置,operator.isCallable
等旧方法更优雅,不成形,面向未来,或检查__call__
等特定特殊方法的存在。由于isinstance
现在可以重载,所以将它留给ABC来重载它,并通过封装任何低级方法最好的方法来执行检查!
新方法的优雅和优势是,如果您需要在较旧版本和较新版本的Python之间移植代码,我建议在可以定义的模块中封装您需要的“鸭子类型测试”其功能取决于sys.version
- 在2.6或更高版本中使用isinstance(x, collections.Y)
,在2.5或更差版本中使用较早的方法,例如hasattr(x, '__somespecialmethod__')
或callable(x)
。
最重要的是,更一般地说,不用旧的,劣等的方式污染新的主线应用程序代码 - 如果向后移植性要求迫使整个系统有一些“垃圾” (为了继续在旧的Python版本上运行),至少要将它自己隐藏在自己的“隔间”中(如果你的应用程序的部署限制允许,有一天你可以轻松扫除它! - )。
答案 1 :(得分:2)
>>> def is_func(instance, func):
test = getattr(instance, func, None)
if test and hasattr(test, '__call__'):
return True
>>> is_func('', 'len')
>>> is_func({}, 'fromkeys')
True
或者您可以使用inspect
模块:
>>> import inspect
>>> test = getattr(cc, 'func', None)
>>> inspect.ismethod(test)
True
答案 2 :(得分:0)
如果方法丢失,你可以抛出某种自定义异常吗? (我来自Ruby的土地:))