python:内置函数的重新定义,具有不同的参数

28 浏览
0 Comments

python:内置函数的重新定义,具有不同的参数

这个问题已经在这里有了答案

Python中__future__用于什么,何时使用它以及它是如何工作的

前言:该问题是为了了解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,它只是一个方便的例子。

admin 更改状态以发布 2023年5月21日
0
0 Comments

在Python 2中,print是一个关键字。你不能重新定义print的原因和你不能重新定义ifwhiledef或其他任何语言关键字相同;它们是语言语法的一部分,它们由解析器处理,而不是通过查找函数来处理。\n\nfrom __future__ import print_function也由解析器处理。它看起来像一个普通的导入语句,它实际上确实导入了一个东西,但它导入的东西与语句的主要功能无关,它的主要功能是告诉解析器停止将print视为关键字。\n\n当关键字被禁用时,print被视为一个普通名称,遵循普通名称查找规则。这种查找会找到通常被关键字隐藏的print内置函数。\n\n你不能定义自己的魔术导入; 它们必须内置到解释器本身。由于你不能定义自己的魔术导入,并且因为没有其他__future__导入将关键字转换为非关键字,所以没有通用性可言。\n\n(有些人会说像listdict这样的内置函数是关键字。它们不是关键字;那些人使用了“关键字”这个词不正确。)\n\n至于使用一个与原始函数不同的签名来monkey-patch内置函数(不是关键字),你可以这样做。这可能是一个坏主意,但你可以这样做。这个过程和平常如何monkey-patch内置函数完全相同。

0
0 Comments

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语句的原始字节码(与delreturn的行为相同;你不能将其命名为这些名字之一,原因是它们是关键字),因此没有导入的模块永远没有机会查找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

0