如何找出在Python中为类的实例定义的函数?

时间:2010-01-18 17:29:12

标签: python reflection function

我想知道是否为类

的实例定义了一个函数
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))

是否有内置或更好的方式来完成我正在寻找的东西?

3 个答案:

答案 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的土地:))