检查它是否是 types.FunctionType
的实例:
>>> import types
>>> isinstance(len, types.FunctionType)
False
>>> def mylen(): pass
...
>>> isinstance(mylen, types.FunctionType)
True
您最好检查是否为isinstance(X, (types.FunctionType, types.LambdaType)
,这样更安全。
C函数是builtin_function_or_method
的实例:
>>> len.__class__
<type 'builtin_function_or_method'>
>>> np.vdot.__class__
<type 'builtin_function_or_method'>
您可以通过
types.BuiltinFunctionType
/
types.BuiltinMethodType
访问此类型。
或者,您可以检查函数是否具有
__code__
属性。由于 C 函数没有字节码,因此它们不能具有
__code__
属性。
请注意,有时看起来像函数的东西实际上是一个类,例如
enumerate
,但某些第三方库可能会执行相同的操作。这意味着您还应检查类是否是用 C 实现的。这比较困难,因为所有类都是
type
的实例。一种方法是检查类的
dir
中是否有
__dict__
,如果没有,则应检查是否有
__slots__
。
以下类似的内容应该是相当准确的:
def is_implemented_in_c(obj):
if isinstance(obj, (types.FunctionType, types.LambdaType)):
return False
elif isinstance(obj, type):
if '__dict__' in dir(obj): return False
return not hasattr(obj, '__slots__')
return not isinstance(obj, types.InstanceType)
使用示例:
>>> is_implemented_in_c(enumerate)
True
>>> is_implemented_in_c(len)
True
>>> is_implemented_in_c(np.vdot)
True
>>> is_implemented_in_c(lambda x: True)
False
>>> is_implemented_in_c(object)
True
>>> class A(object):
... __slots__ = ('a', 'b')
...
>>> is_implemented_in_c(A)
False
dis
模块阅读源代码/反汇编并找到真正的 C 函数。 - Bakuriuis_implemented_in_c()
函数假定存在 Python 2.x 特有的types.InstanceType
属性来检测旧式类,但是在 Python 3.x 中已经不存在了(出于显而易见的原因)。该函数并没有像它所宣传的那样工作。事实上,它的错误程度非常可怕。在 CPython 下,基于 C 的对象可以通过以下代码片段轻松检测到:is_obj_c = bool(type(obj).__flags__ & (1<<9))
,其中(1<<9)
是位于官方 CPython 代码库中的Include/object.h
C 头文件中的魔数_Py_TPFLAGS_HEAPTYPE
。 - Cecil Curry