python:内置函数的重新定义,具有不同的参数
python:内置函数的重新定义,具有不同的参数
这个问题已经在这里有了答案:
前言:该问题是为了了解Python内部工作原理,请不要回答“升级Python”或“导入six”
以“print”为例
要替换“print”内置函数,我可以编写我自己的Python函数。
Python 2.6:运行时会收到语法错误
解决方案
from __future__ import print_function
现在我可以重新定义print。
为什么?
我认为是因为现在我的print声明与新的print函数相同。
Python 2.4:运行时会收到语法错误
没有
from __future__ import print_function
因此,对于print
(或任何其他内置函数):是否可以使用具有不同声明(args和kwargs)的新函数进行monkey patch?
换句话说。
from __future__ import print_function
将该关键字替换为一个函数。我想了解一般情况下是如何实现的。请不要仅仅关注于print
,它只是一个方便的例子。
在Python 2中,print
是一个关键字。你不能重新定义print
的原因和你不能重新定义if
,while
,def
或其他任何语言关键字相同;它们是语言语法的一部分,它们由解析器处理,而不是通过查找函数来处理。\n\nfrom __future__ import print_function
也由解析器处理。它看起来像一个普通的导入语句,它实际上确实导入了一个东西,但它导入的东西与语句的主要功能无关,它的主要功能是告诉解析器停止将print
视为关键字。\n\n当关键字被禁用时,print
被视为一个普通名称,遵循普通名称查找规则。这种查找会找到通常被关键字隐藏的print
内置函数。\n\n你不能定义自己的魔术导入; 它们必须内置到解释器本身。由于你不能定义自己的魔术导入,并且因为没有其他__future__
导入将关键字转换为非关键字,所以没有通用性可言。\n\n(有些人会说像list
或dict
这样的内置函数是关键字。它们不是关键字;那些人使用了“关键字”这个词不正确。)\n\n至于使用一个与原始函数不同的签名来monkey-patch内置函数(不是关键字),你可以这样做。这可能是一个坏主意,但你可以这样做。这个过程和平常如何monkey-patch内置函数完全相同。
from __future__ import print_function
只是在解析器中切换一个标志位,使其停止将print
当作关键字处理;一旦完成,对print
的引用就自然地变成了对任何其他合法变量名称的非关键字引用(它们通过LEGB查找,可以在LEGB中的内建作用域中找到)。这种行为在Python解释器中被硬编码了;没有任何办法能够实现对任何其他关键字的类似效果,除非构建一个定制版本的Python,或者进行某些其他超出任何合理问题范围的不当修改。
自2.6起, __builtin__
有一个print
函数,因此任何使用from __future__ import print_function
的模块(并且可以因此引用名称print
而不是关键字print
)将会看到__builtin__ .print
(如果它没有被本地、嵌套或全局作用域中的某些东西所遮蔽)。它仍然存在于每个模块中,但在没有__future__
导入的模块中,对print
的引用在编译时被解析为关键字并替换为实现特殊print
语句的原始字节码(与del
和return
的行为相同;你不能将其命名为这些名字之一,原因是它们是关键字),因此没有导入的模块永远没有机会查找print
函数。
这并不适用于其他情况,因为__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