Python内置函数与类型的深度辨析:从dir到inspect的完整解析
本文深入解析Python 3.10中的内置函数与类型。通过dir(__builtins__)获取名称列表,利用eval和inspect模块区分内置函数(BuiltinFunctionType)与内置类(如str, list)。文章详细演示了如何识别构造器调用与函数调用的本质区别,并提供三种检测内置成员的方法,帮助开发者准确理解Python的底层类型机制。

该图表源自python.org,展示了Python 3.10版本中列出的所有内置函数。
然而,这些名称是否全部代表真正的函数呢?
我们可以通过以下代码进行测试:
import types
import inspect
lst = dir(__builtins__)
for name in lst:
print(name, eval(f'type({name})'))
变量lst获取的是__builtins__模块中所有内容的名称,因此lst是一个包含字符串的列表。但每个字符串所指向的对象含义各异。例如,字符串"sum"对应的是一个内置函数,而字符串"str"对应的则是一个内置类。
利用eval执行type函数,我们可以获取每个name对应的type对象描述,具体示例如下:
bool <class 'type'>
至此我们可以发现,诸如type、dict、str、range、list、tuple、zip等,实际上并非函数名称,而是类型名称:
dict <class 'type'> list <class 'type'> map <class 'type'> range <class 'type'> set <class 'type'> str <class 'type'> tuple <class 'type'> type <class 'type'> zip <class 'type'>
因此,类似range(10)或type("c")这样的写法,实质上是调用构造器来创建相应类型的实例。
接下来,我们进一步深入,分别输出__builtins__模块中的所有内置函数和内置类型。
以下是输出内置函数的代码示例:
import types
import inspect
lst = dir(__builtins__)
for name in lst:
if eval(f'type({name})') is types.BuiltinFunctionType:
print(f'{name}是内置函数')
if inspect.isbuiltin(getattr(__builtins__, name)):
print(f'{name}是内置函数')
fs = inspect.getmembers(__builtins__, inspect.isbuiltin)
print(fs)
这里演示了三种不同的检测方法:
1. 如果其type对象属于types.BuiltinFunctionType,则表明这是一个内置函数。
2. 在Python中一切皆对象,getattr(__builtins__, name)的作用是将__builtins__模块视为对象,从中获取名为name的具体内容,这体现了Python中的反射机制。获取具体内容后,利用inspect模块的isbuiltin函数来检测是否为内置函数。(注意:inspect模块的isfunction函数仅适用于检测普通函数,无法正确识别内置函数,因为内置函数并非普通函数,使用isfunction检测内置函数会返回False,必须使用isbuiltin函数进行检测。)
3. 既然__builtins__是一个对象,完全可以利用inspect的getmembers函数,并传入过滤器inspect.isbuiltin,从而直接过滤出__builtins__中的所有内置函数。
接下来是输出内置类的部分:
import types
import inspect
lst = dir(__builtins__)
for name in lst:
print(name, eval(f'type({name})'))
for name in lst:
if inspect.isclass(getattr(__builtins__, name)):
print(f'{name}是内置类')
cs = inspect.getmembers(__builtins__, inspect.isclass)
print(cs)
由于types模块中没有专门针对类的检测类型,因此这里统一使用inspect.isclass进行检测。
换句话说,内置类本质上也是类。
总结
本文到此结束,希望能为读者带来帮助,同时也欢迎大家关注本站以获取更多相关内容!
免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









