为什么Python中的__builtins__不包含自身?
关于Python内置对象
__builtins__的疑问 问题背景
我尝试用以下代码分类概览Python的内置对象:
dunder = [] # 8 lower_fun = [] # 41 lower_type = [] # 26 lower_sitebuiltins = [] # 6 upper_exception = [] # 50 upper_warning = [] # 11 upper_other = [] # 10 for name, obj in vars(__builtins__).items(): first_char = name[0] if first_char == '_': dunder.append(name) else: if first_char.islower(): t = str(type(obj)) if t == "<class 'builtin_function_or_method'>": lower_fun.append(name) elif t == "<class 'type'>": lower_type.append(name) elif '_sitebuiltins' in t: lower_sitebuiltins.append(name) else: assert False # does not happen else: if 'Error' in name or 'Exception' in name: upper_exception.append(name) elif 'Warning' in name: upper_warning.append(name) else: upper_other.append(name)
原本我预期__builtins__会出现在dunder列表里,但实际结果中:
dunder == [ '__name__', '__doc__', '__package__', '__loader__', '__spec__', '__build_class__', '__import__', '__debug__' ]
显然我对“内置”的含义理解有误,想请教:
vars(__builtins__)返回的152个条目具体是什么?- 还有哪些类似
__builtins__的内容没被包含进来?
补充说明
builtins和sys也不在上述分类列表中- 152个条目是运行Python脚本文件得到的结果;在交互式控制台中,
dir(__builtins__)只有41个条目,且调用vars(__builtins__)会触发TypeError - 最初代码用的是
dir(__builtins__),后来改成vars(__builtins__),结果本质一致,只是列表顺序不同
解答
1. vars(__builtins__)的152个条目到底是什么
首先得搞清楚__builtins__的本质:
- 在脚本文件(非交互式环境)里,
__builtins__其实就是builtins模块本身,所以vars(__builtins__)返回的是这个模块的命名空间字典,里面包含了所有内置函数、类型、异常、警告,以及模块自身的特殊属性,总数刚好是你看到的152个。 - 而在交互式控制台里,
__builtins__是builtins.__dict__的一个特殊代理,属于dict实例但被做了限制,不能直接用vars()调用,所以会报错;此时dir(__builtins__)只展示了常用的内置对象(比如print、list),所以只有41个条目。
你分类出的各个列表,其实就是对builtins模块所有成员的拆分:
dunder列表里是模块自身的特殊属性(比如__name__是模块名,__import__是内置导入函数等)lower_fun是所有内置函数/方法(比如print、len)lower_type是所有内置类型(比如list、dict、int)lower_sitebuiltins是CPython中由_sitebuiltins模块提供的特殊对象(比如quit、exit)upper_exception和upper_warning是所有内置异常和警告类upper_other是其他首字母大写的内置对象(比如Ellipsis、NotImplemented)
2. 为什么__builtins__、builtins、sys不在列表里
__builtins__本身是当前作用域对builtins模块的引用,它并不是builtins模块内部的成员,自然不会出现在vars(__builtins__)的结果里。builtins是模块自身的引用,但builtins模块的命名空间里并没有把自身作为成员存储,所以也不会出现在结果中。如果要获取它,得手动import builtins。sys是独立的标准库模块,不属于builtins的范畴,必须手动import sys才能使用,所以当然不会出现在内置对象列表里。
内容的提问来源于stack exchange,提问作者Watchduck
相关产品推荐
相关产品推荐

