0

我对“Learning Python”一书中的代码有点困惑,p。539.

据我所知,函数内的分配仅在此本地范围内。所以如果我想改变一个全局的,我首先必须声明它global。但是为什么下面的代码一旦调用builtin.open()就完全改变了?custom

import builtins
def makeopen(id):
    original = builtins.open
    def custom(*pargs, **kargs):
        print('Custom open call %r: ' % id, pargs, kargs)
        return original(*pargs, **kargs)
    builtins.open = custom

如果我打电话makeopen('spam')F = open('text.txt')然后我custom接到电话。所以.builtin.open()之后整个脚本中的makeopen('spam'). 为什么?如果我再做一些,makeopen('xx')就会为每个 createdbuiltin.open('text.txt')打印调用。为什么?custommakeopen

将此代码与

x = 99
def changing():
    x = 88
changing()
print(x)

甚至不帮助我。不是一样,而是用一个x代替builtin.open()吗?

4

1 回答 1

0

如果您在函数中的任何位置分配变量,则该变量被视为局部变量,除非您将其声明为全局变量。

在您的第一段代码中,您从未将任何内容分配给builtins,因此它不被视为本地代码。您只需更改其属性之一,open.

遵守规则!

在您的第二段代码中,您将某些内容分配给xin x = 88,因此它被认为是本地的。


当您调用 时makeopen,您将原来的全局替换opencustomcustom, 执行时,打印其名称并调用原始打开。

如果您makeopen第二次调用,它将创建第二个不同的custom函数,并让名称builtins.open引用它。当你调用这个函数时,它会打印它的名字,然后调用original它,这就是builtins.open它创建时所引用的——这是你的第一个custom函数,它将打印它的名字并调用原来的open.

因此,连续调用makeopen创建一个函数链,并且调用open将使它们中的每一个运行并调用其前身。

于 2020-08-08T08:56:43.700 回答