Python3`builtins`并不总是`__builtins__`

时间:2019-02-18 17:02:24

标签: python python-3.x

我将这个想法How to make a cross-module variable?用于python3。 而且很懒,可以使用变量__builtins__而不是模块builtins。哪个应该没什么不同,因为:

# file spam.py:
import builtins
print (builtins is __builtins__)
print (id(builtins))
print (id(__builtins__))

这是在变得有趣的时候:导入时builtins不是__builtins__

$ python3 spam.py 
True
140598001743336
140598001743336

$ python3 -c 'import spam'
False
139755426543080
139755426520904

有人知道会发生什么吗?

(在给定页面上的注释中提到“ __builtins__是CPython的特殊之处,您确实不应该使用它”,但我很好奇...)

2 个答案:

答案 0 :(得分:3)

我真的不知道为什么,但是来自article

  

框架全局变量具有一个__builtins__变量(内置字典,或者   __name__等于__main__时的内置模块

因此,在第一种情况(__name__ == __main__)中,您将__builtins__作为builtins模块,但在第二种情况(__name__ != __main____builtins__dict实例和docs中的实例:

  

__builtins__的值通常是此模块或值   该模块的__dict__属性的值。

测试

稍作修改的spam.py

import builtins

if __name__ == '__main__':
    print(type(__builtins__))
    print(__builtins__ is builtins)
    print(id(builtins))
    print(id(__builtins__))
else:
    print(type(__builtins__))
    print(__builtins__ is builtins.__dict__)
    print(id(builtins.__dict__))
    print(id(__builtins__))

我们会得到类似的东西

$ python3 spam.py 
<class 'module'>
True
2345652270648
2345652270648

$ python3 -c 'import spam'
<class 'dict'>
True
2770543697736
2770543697736

结论

您和@chepner已经注意到__builtins__是可以更改的实现细节,因此我们不应该依赖它,尤其是将其作为builtins模块/ {{1} }对象。

答案 1 :(得分:1)

对于 CPython 实现,

__main__ 模块中:__builtins__ is builtins.
在其他模块中:__builtins__ is builtins.__dict__

参考:
https://docs.python.org/3/reference/executionmodel.html#builtins-and-restricted-execution http://mathamy.com/whats-the-deal-with-builtins-vs-builtin.html