Python - 测试对象是否为内置函数

14

有没有一种简单的方法来检查对象o是否为内置的Python函数?

我知道我可以使用,例如

type(o) == type(pow)

因为type(pow)是“builtin_function_or_method”。

但是有没有更好的方法呢?

6个回答

20

types模块:

>>> import types
>>> types.BuiltinFunctionType
<type 'builtin_function_or_method'>

虽然,如果你深入了解,你会发现它并没有和你现在所做的有太大区别。

因此,在您的情况下,请使用

isinstance(o, types.BuiltinFunctionType)

3
这并不告诉你一个函数是否是内置函数,而是告诉你它是否是原生编译的 C 函数。带有 C 扩展的第三方模块也会将它们的函数报告为这种类型。 - Ned Batchelder
1
@ThomasVanderStichele:是的,不幸的是,原帖没有提供太多上下文,也没有告诉我们他对“builtin”的哪个方面感兴趣。 - Ned Batchelder
当对象是内置类型,例如int时,这似乎不起作用。以下两个示例都返回False:isinstance(int, (types.BuiltinFunctionType, types.BuiltinMethodType))isinstance(int.__init__, (types.BuiltinFunctionType, types.BuiltinMethodType))。有没有办法处理这种情况? - Scott H
1
@ScottH:内置类型(例如int)是类而不是可调用对象。因此,当然,int既不是内置函数也不是方法;它是一种类型。换句话说,这确实像广告中所说的那样工作。你想要的是决定给定类是在纯Python中实现还是作为C扩展,这是一个完全正交的问题。 - Cecil Curry
@CecilCurry,有没有一种方法可以检查一个类型是否是内置标准库的一部分?(无论是用C实现还是纯Python) - Scott H
显示剩余2条评论

6

取决于您所说的“内置”是指什么。

使用__builtins__

如果您想要检查您的函数是否为Python解释器中内置的函数之一,您可以使用

>>> pow in __builtins__.__dict__.values()
True
>>> __builtins__.__dict__['pow']
<built-in function pow>

Python解释器有一些内置的常量、函数、类型和异常,它们包含在字典__builtins__.__dict__中。
如果你想检查你的函数是否属于BuiltinFunctionType类型,可以使用types模块。
>>> import types
>>> isinstance(pow, types.BuiltinFunctionType)
True

使用 inspect

或者使用 inspect.isbuiltin(它只是对 isinstance(object, types.BuiltinFunctionType) 的包装)。

>>> import inspect
>>> inspect.isbuiltin(pow)
True
BuiltinFunctionType 中的 "built-in" 一词表示 "用C语言编写"。请看以下示例:
>>> from math import factorial
>>> isinstance(factorial, types.BuiltinFunctionType)
True

factorial函数的类型为BuiltinFunctionType,但它不是解释器中的内置函数。

>>> factorial in __builtins__.__dict__.values()
False

这是因为Python中的math模块由C语言编写的数学库函数包装而成。

能够检测到BuiltinFunctionType很有用,因为对于使用Python编写的函数,我们可以在不打开源文件的情况下检查源代码。

>>> import random
>>> isinstance(random.random, types.BuiltinFunctionType)
True
>>> inspect.getsource(random.random)
# returns TypeError
>>> isinstance(random.uniform, types.BuiltinFunctionType)
False
>>> from __future__ import print_function # if using Python 2.*
>>> print(inspect.getsource(random.uniform))
    def uniform(self, a, b):
        "Get a random number in the range [a, b) or [a, b] depending on rounding."
        return a + (b-a) * self.random()

1
值得注意的是,在Python 3中,“map”被错误地分类为类而不是函数,因为它在技术上已经成为一个类。 - Ehsan Kia

3

试试这个:

>>> import types
>>> isinstance(pow, types.BuiltinFunctionType)
True
>>> def a():
    pass
>>> isinstance(a, types.BuiltinFunctionType)
False

2
您可以做以下操作:
import __builtin__
o in __builtin__.__dict__.values()

或者,在CPython中:
o in __builtins__.__dict__.values()

请注意,你在这里依赖于一个实现细节。


>>> pow in __builtins__.__dict__.values()
True
>>> def a():
...   pass
...
>>> a in __builtins__.__dict__.values()
False
>>>

1
您可以检查内置属性是否存在并且可调用。示例:
>>> import builtins
>>> hasattr(builtins, 'max')
True
>>> hasattr(builtins, 'abs')
True
>>> hasattr(builtins, 'aaa')
False
>>> hasattr(builtins, 'True')
True
>>> callable(abs)
True
>>> callable(True)
False
>>> hasattr(builtins, 'max') and callable(max)
True
>>> hasattr(builtins, 'True') and callable(True)
False

1
虽然时间有些过去了,但是或许其他人会发现我的答案有用,因为我在寻找答案时也遇到了这个问题。
如果你只是想测试一个变量var是否属于以下情况之一:
  1. function
  2. builtin_function_or_method 但不是method
我发现以下测试可以工作:
import types

def is_func(arg):
    return isinstance(arg, types.FunctionType) or \
        (isinstance(arg, types.BuiltinFunctionType) and
            arg.__self__ is None)

希望我的假设是正确的,但总体思想是,如果我们已经得到了一个builtin_method,它必须具有与之关联的非None类型。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接