2024-10-08 19:28:00 发布
网友
当我运行这段代码时,我得到的结果是:
15 15
我希望输出应该是
但事实并非如此。问题是:为什么?在
def make_adder_and_setter(x): def setter(n): x = n return (lambda y: x + y, setter) myadder, mysetter = make_adder_and_setter(5) print myadder(10) mysetter(7) print myadder(10)
python2.x有一个语法限制,不允许在读/写时捕获变量。在
原因是,如果在函数中指定变量,则只有两种可能性:
global x
更具体地说,它排除了变量是封闭函数作用域的局部变量
在python3.x中,这已经被添加了nonlocal声明所取代。在python3中,您的代码将按预期工作,方法是
nonlocal
def make_adder_and_setter(x): def setter(n): nonlocal x x = n return (lambda y: x + y, setter)
Python2.x运行时能够在字节码级别处理closed over变量的读写操作,但是编译器接受的语法存在局限性。在
您可以看到一个lisp编译器,它直接生成python字节码,它创建一个具有读写捕获状态at the end of this video的加法器闭包。编译器可以为python2.x、python3.x或PyPy生成字节码。在
如果在Python 2.x中需要closed over mutable state,一个窍门是使用一个列表:
内部的def setter(n)函数定义了它自己的局部变量x。这将隐藏另一个x变量,该变量是make_adder_and_setter的参数(在作用域中形成一个洞)。因此setter函数没有副作用。它只设置内部局部变量的值并退出。在
def setter(n)
x
make_adder_and_setter
setter
如果您尝试下面的代码,可能会对您很清楚。它做的完全一样,只是用了z的名字而不是x
def make_adder_and_setter(x): def setter(n): z = n return (lambda y: x + y, setter) myadder, mysetter = make_adder_and_setter(5) print myadder(10) mysetter(7) print myadder(10)
您正在setter()函数中设置一个局部变量x。对函数中的名称赋值会将其标记为本地名称,除非您特别告诉Python编译器。在
setter()
在Python3中,可以使用nonlocal关键字显式地将x标记为非本地的:
现在,x被标记为一个自由变量,并在分配给时在周围的范围中查找。在
在python2中,不能将Python标记为本地的。唯一的另一个选项是将x标记为global。您将不得不使用一些技巧来更改位于周围范围内的可变对象所包含的值。在
global
在setter函数上的属性可以工作,例如,setter是make_adder_and_setter()作用域的本地属性,任何可以访问setter的对象都可以看到该对象上的属性:
make_adder_and_setter()
另一个技巧是使用可变容器,例如列表:
def make_adder_and_setter(x): x = [x] def setter(n): x[0] = n return (lambda y: x[0] + y, setter)
在这两种情况下,不再分配给本地名称;第一个示例使用setter对象的属性赋值,第二个示例更改x列表,而不是赋值给x本身。在
python2.x有一个语法限制,不允许在读/写时捕获变量。在
原因是,如果在函数中指定变量,则只有两种可能性:
global x
声明更具体地说,它排除了变量是封闭函数作用域的局部变量
在python3.x中,这已经被添加了
nonlocal
声明所取代。在python3中,您的代码将按预期工作,方法是Python2.x运行时能够在字节码级别处理closed over变量的读写操作,但是编译器接受的语法存在局限性。在
您可以看到一个lisp编译器,它直接生成python字节码,它创建一个具有读写捕获状态at the end of this video的加法器闭包。编译器可以为python2.x、python3.x或PyPy生成字节码。在
如果在Python 2.x中需要closed over mutable state,一个窍门是使用一个列表:
^{pr2}$内部的
def setter(n)
函数定义了它自己的局部变量x
。这将隐藏另一个x
变量,该变量是make_adder_and_setter
的参数(在作用域中形成一个洞)。因此setter
函数没有副作用。它只设置内部局部变量的值并退出。在如果您尝试下面的代码,可能会对您很清楚。它做的完全一样,只是用了z的名字而不是x
您正在
setter()
函数中设置一个局部变量x
。对函数中的名称赋值会将其标记为本地名称,除非您特别告诉Python编译器。在在Python3中,可以使用
nonlocal
关键字显式地将x
标记为非本地的:现在,
x
被标记为一个自由变量,并在分配给时在周围的范围中查找。在在python2中,不能将Python标记为本地的。唯一的另一个选项是将
x
标记为global
。您将不得不使用一些技巧来更改位于周围范围内的可变对象所包含的值。在在
^{pr2}$setter
函数上的属性可以工作,例如,setter
是make_adder_and_setter()
作用域的本地属性,任何可以访问setter
的对象都可以看到该对象上的属性:另一个技巧是使用可变容器,例如列表:
在这两种情况下,不再分配给本地名称;第一个示例使用
setter
对象的属性赋值,第二个示例更改x
列表,而不是赋值给x
本身。在相关问题 更多 >
编程相关推荐