python:内置函数重新定义,使用不同的参数

python:内置函数重新定义,使用不同的参数,python,built-in,monkeypatching,Python,Built In,Monkeypatching,前言:问题是要理解python的内部结构,所以请不要用“升级python”或“导入6”来回答 以“打印”为例 为了替换“print”内置函数,我可以编写python函数 Python2.6:在运行时,我发现语法错误 解决方案 from __future__ import print_function 现在我可以重新定义打印了。 为什么? 我认为,因为现在我的打印声明与新的打印函数相同 python 2.4:在运行时,我发现语法错误 没有 from __future__ import print

前言:问题是要理解python的内部结构,所以请不要用“升级python”或“导入6”来回答

以“打印”为例

为了替换“print”内置函数,我可以编写python函数

Python2.6:在运行时,我发现语法错误

解决方案

from __future__ import print_function
现在我可以重新定义打印了。 为什么? 我认为,因为现在我的打印声明与新的打印函数相同

python 2.4:在运行时,我发现语法错误

没有

from __future__ import print_function
那么,对于print或任何其他内置程序:是否有可能使用一个新函数和一个不同的声明(args和kwargs)来monkey patch

换句话说

from _ufuture _; import print_函数用函数替换关键字。总的来说,我想知道怎么做。请不要只关注打印,这是一个方便的示例。

在Python 2中,打印是一个关键字。不能重新定义打印,原因与不能重新定义if、while、def或任何其他语言关键字相同;它们是语言语法的一部分,由解析器处理,而不是通过查找函数

from _ufuture _; import print_函数也由解析器处理。它看起来像一个普通的导入,实际上它导入了一个东西,但它导入的东西与语句的主要功能无关,即告诉解析器停止将print作为关键字处理

禁用关键字后,打印将按照普通名称查找规则被视为普通名称。这样的查找会找到内置函数,该函数通常由关键字隐藏

您无法定义自己的魔法导入;它们必须内置到解释器中。由于您无法定义自己的魔法导入,并且由于没有其他“未来”导入将关键字转换为非关键字,因此不需要进行泛化

人们有时会说像list或dict这样的内置词是关键字。它们不是关键词;那些人用词不当

至于猴子补丁的内置功能,而不是与原始关键字具有不同签名的关键字,您可以这样做。这可能是个坏主意,但你可以做到。这一过程与通常使用猴子修补内置程序的过程相同。

在Python2中,print是一个关键字。不能重新定义打印,原因与不能重新定义if、while、def或任何其他语言关键字相同;它们是语言语法的一部分,由解析器处理,而不是通过查找函数

from _ufuture _; import print_函数也由解析器处理。它看起来像一个普通的导入,实际上它导入了一个东西,但它导入的东西与语句的主要功能无关,即告诉解析器停止将print作为关键字处理

禁用关键字后,打印将按照普通名称查找规则被视为普通名称。这样的查找会找到内置函数,该函数通常由关键字隐藏

您无法定义自己的魔法导入;它们必须内置到解释器中。由于您无法定义自己的魔法导入,并且由于没有其他“未来”导入将关键字转换为非关键字,因此不需要进行泛化

人们有时会说像list或dict这样的内置词是关键字。它们不是关键词;那些人用词不当

至于猴子补丁的内置功能,而不是与原始关键字具有不同签名的关键字,您可以这样做。这可能是个坏主意,但你可以做到。该过程与您正常使用猴子修补内置程序的过程相同。

来自未来导入打印的所有功能都是在解析器中切换一个标志,使其停止将打印作为关键字处理;一旦完成,打印的引用将无缝地变成对构成合法变量名的任何其他非关键字的引用。它们通过LEGB查找,并在LEGB的B中找到,即内置范围。这种行为在Python解释器中被硬编码;如果不构建Python的自定义版本,或者不参与超出任何合理问题范围的其他骇人听闻的黑客行为,就无法实现任何其他关键字的类似效果

从2.6开始,uuuu builtin_uuuuuuuu上有一个print函数,因此任何使用from uuu future uuuuuuu导入print_u函数的模块,如果没有被本地、嵌套或全局范围中的某个对象遮挡,则可以引用名称print而不是关键字print,则会看到uuuu builtin uuuuuuu.print。它仍然存在于每个模块中,但在没有“未来”导入的模块中,对print的引用在编译时解析为关键字,并替换为原始字节码,以del和return相同的方式实现特殊的print语句;出于同样的原因,您不能命名这些东西中的任何一个变量,它们是关键字,因此没有导入的模块永远不会有机会 以查找打印功能

这并不能推广到其他情况,因为_future _uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu。对于所有其他实际内置函数,能够在每个模块的基础上覆盖它们就像在全局范围内为该模块的名称分配阴影一样简单,例如:

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
函数所做的一切就是在解析器中切换一个标志,使其停止将打印作为关键字处理;一旦完成,打印的引用将无缝地变成对构成合法变量名的任何其他非关键字的引用。它们通过LEGB查找,并在LEGB的B中找到,即内置范围。这种行为在Python解释器中被硬编码;如果不构建Python的自定义版本,或者不参与超出任何合理问题范围的其他骇人听闻的黑客行为,就无法实现任何其他关键字的类似效果

从2.6开始,uuuu builtin_uuuuuuuu上有一个print函数,因此任何使用from uuu future uuuuuuu导入print_u函数的模块,如果没有被本地、嵌套或全局范围中的某个对象遮挡,则可以引用名称print而不是关键字print,则会看到uuuu builtin uuuuuuu.print。它仍然存在于每个模块中,但在没有“未来”导入的模块中,对print的引用在编译时解析为关键字,并替换为原始字节码,以del和return相同的方式实现特殊的print语句;出于同样的原因,您不能命名这些东西中的任何一个变量,因为它们是关键字,所以没有导入的模块永远不会有机会查找打印函数

这并不能推广到其他情况,因为_future _uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu。对于所有其他实际内置函数,能够在每个模块的基础上覆盖它们就像在全局范围内为该模块的名称分配阴影一样简单,例如:

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

在Python2中,print是一个不能指定的关键字。在Python3中,print只是一个可以重新指定名称的函数__future\uuuuu导入有点神奇。这里不是专业人士,但从future import print可以告诉解释器加载python 3 stlye打印函数-对于python 2x打印,它不是一个函数,而是一个受保护的关键字,可以防止被重新定义IDE注意:文档声明来自于\uuuu future\uuuuuuuuuuu导入打印函数,所以它在2.5版本中工作有点奇怪…@ShadowRanger Thnks,你是对的,我把它和“with_语句”混淆了。我的问题仍然存在。你说请不要只关注印刷品,这是一个方便的例子。但实际上,没有什么比Python2上的打印更好的了。在其他任何情况下,未来导入都不会将关键字更改为非保留字。有些导入会将非保留字更改为关键字,但print_函数是从关键字转换为非关键字的唯一情况。在Python 2中,print是一个无法分配的关键字。在Python3中,print只是一个可以重新指定名称的函数__future\uuuuu导入有点神奇。这里不是专业人士,但从future import print可以告诉解释器加载python 3 stlye打印函数-对于python 2x打印,它不是一个函数,而是一个受保护的关键字,可以防止被重新定义IDE注意:文档声明来自于\uuuu future\uuuuuuuuuuu导入打印函数,所以它在2.5版本中工作有点奇怪…@ShadowRanger Thnks,你是对的,我把它和“with_语句”混淆了。我的问题仍然存在。你说请不要只关注印刷品,这是一个方便的例子。但实际上,没有什么比Python2上的打印更好的了。在其他情况下,“未来”导入不会将关键字更改为非保留字一些导入会将非保留字更改为关键字,但打印功能是唯一从关键字更改为非关键字的情况。有趣的实现细节:一旦“将来”导入“打印”功能可用,即使未激活,打印是一个内置项,您可以使用vars\uuuu内置项\uuuu['print']访问它。只是,除非将来的功能处于活动状态,否则在LEGB查找之前,作为关键字的print将生效,因此,除非您使用奇怪的黑客从内置的字符串名称中提取print,否则您永远不会尝试查找名称print。'from future import print_function'将关键字替换为函数。总的来说,我想知道怎么做。请不要只关注打印,这是一个很好的例子。@Massimo:from _u\u future _u\u import print_函数的情况是uniqu
E没有其他内置函数需要这种繁琐的操作,因为print是唯一的,在Py2上,它默认为关键字语句,比如del、return等,而不是函数。这就是为什么你通常不能更换它。其他的一切要么永远是一个关键字语句永远不能被替换,要么永远是一个内置函数可以被替换,尽管这通常是一个坏主意。但这不是一般性的。这是解析器中关闭关键字的一种特殊的黑客行为。它没有通用版本。from _future _导入…,尽管共享相同的语法,但不是常规导入。它从根本上改变了解析器识别的语言,这就是为什么它必须是模块中的第一条语句。注意,getattr\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu。只是,除非将来的功能处于活动状态,否则在LEGB查找之前,作为关键字的print将生效,因此,除非您使用奇怪的黑客从内置的字符串名称中提取print,否则您永远不会尝试查找名称print。'from future import print_function'将关键字替换为函数。总的来说,我想知道怎么做。请不要只关注打印,这是一个方便的例子。@Massimo:from _ufuture _u导入打印功能的情况是唯一的;没有其他内置函数需要这种繁琐的操作,因为print是唯一的,在Py2上,它默认为关键字语句,比如del、return等,而不是函数。这就是为什么你通常不能更换它。其他的一切要么永远是一个关键字语句永远不能被替换,要么永远是一个内置函数可以被替换,尽管这通常是一个坏主意。但这不是一般性的。这是解析器中关闭关键字的一种特殊的黑客行为。它没有通用版本。from _future _导入…,尽管共享相同的语法,但不是常规导入。它从根本上改变了解析器识别的语言,这就是为什么它必须是模块中的第一条语句。请注意,getattr_uuuuuuuuuuuuuuuuuuuuuuuuuuuhi内置的“打印”功能在没有uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu__带s的内置是一个奇怪的自动导入的CPython实现细节,它提供了与官方的相同的属性,但没有带s的自动导入的内置。我承认这种区别是令人困惑的,所以一致地使用内置的并不影响任何东西;具体来说,在模块内部,内置通常是模块的dict,而不是模块本身。使用uuu内置\uuuu/内置而不是uuu内置\uuuu可以避免这种怪癖。@user2357112:True。忘了那一点古怪。我收回我极轻微的反对意见-我以印刷品为例。。。这是个特例,唉!现在很清楚为什么在旧的Python2.x上我不能修补它了。@user2357112:那个编辑实际上是不必要的__带s的内置是一个奇怪的自动导入的CPython实现细节,它提供了与官方的相同的属性,但没有带s的自动导入的内置。我承认这种区别是令人困惑的,所以一致地使用内置的并不影响任何东西;具体来说,在模块内部,内置通常是模块的dict,而不是模块本身。使用uuu内置\uuuu/内置而不是uuu内置\uuuu可以避免这种怪癖。@user2357112:True。忘了那一点古怪。我收回我极轻微的反对意见-我以印刷品为例。。。这是个特例,唉!现在很清楚为什么在旧的Python2.x上我不能修补它。