前言:问题是了解python内部结构,所以请不要用'upgrade python'或'import six'来回答
以“打印”为例
要替换内置的“print”,我可以编写我的 python 函数。
python 2.6:在运行时,我得到语法错误
解决方案
from __future__ import print_function
现在我可以重新定义打印了。
为什么 ?
我想是因为现在我的 print 声明与新的 print 函数相同。
python 2.4:在运行时,我得到语法错误
没有
from __future__ import print_function
那么,对于 print
(或任何其他内置函数):是否有可能使用新函数使用不同的声明 - args 和 kwargs 来猴子补丁?
换句话说。
from __future__ import print_function
用函数替换关键字。一般来说,我想了解如何。请不要只关注 print
,这是一个方便的示例。
from __future__ import print_function
所做的只是在解析器中切换一个标志,使其停止将 print
视为关键字;一旦完成,对 print
的引用就会无缝地变成对构成合法变量名的任何其他非关键字的引用(它们通过 LEGB 查找,并在 LEGB 的 B 中找到,即内置范围) .这种行为在 Python 解释器中是硬编码的;如果不构建自定义版本的 Python,或者参与其他一些超出任何合理问题范围的令人震惊的骇客行为,就无法对任何其他关键字实现类似的效果。
从 2.6 开始,__builtin__
有一个 print
函数,所以任何使用 from __future__ import print_function
的模块(因此可以引用name print
而不是 keyword print
) 将看到 __builtin__.print
(如果它没有被本地、嵌套或全局范围内的某些东西遮蔽)。对于每个模块,它仍然存在,但是在没有__future__
导入的模块中,对print
的引用被解析为关键字在编译时替换为实现特殊 print
语句 的原始字节码(与 del
和 return
相同行为;出于同样的原因,您不能命名变量,它们是关键字),因此没有导入的模块永远没有机会查找 print
function.
这不会推广到其他情况,因为 __future__
没有其他情况,其中一个功能可以将关键字转换为非关键字。对于所有其他实际的内置函数,能够在每个模块的基础上覆盖它们就像在全局范围内分配名称一样简单(为该模块隐藏它),例如:
def abs(x):
return x # Who needs absolute value anyway?
# From here on out, references to abs in this module see your override, not the built-in
虽然可以在全局范围内重新分配内置函数,但这是一个糟糕的想法(因为使用它的每个其他模块都可能依赖于内置函数的原始行为)。也就是说,这并不难:
import __builtin__
def abs(x):
return x # Who needs absolute value anyway?
__builtin__.abs = abs
# *Every* module now sees your terrible monkeypatch, on your own head be it