确定是否已在C扩展中实现Python函数

时间:2013-05-25 04:55:16

标签: python cython

假设我有一个Python程序运行缓慢 - 在profiliing之后我发现了瓶颈。我导入的第三方模块的一个特定功能特别慢。

对于这种特殊情况,我知道该函数是用Python实现的(使用Eclipse并且很容易跳转到函数定义)。所以我知道我可以将该函数转换为Cython作为加速选项。 (如果它已经在C中实现,那么在Cython中编写它是没有意义的......)。

如果我没有IDE,那么确定这个是一个简单的选择吗? 我知道我可以转到安装模块的目录,如果模块在.so中,则推断它在C中。但还有其他选择吗?

由于

1 个答案:

答案 0 :(得分:2)

检查它是否是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__

有时注意看起来像一个函数实际上是class,例如enumerate但是某些第三方图书馆也可以这样做。这意味着您还应该检查一个类是否在C中实现。这个更难,因为所有类都是type的实例。一种方法可能是检查班级__dict__中是否有dir,如果没有,则应检查__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__')
    # We accept also instances of classes.
    # Return True for instances of C classes, False for python classes.
    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