Learning Python Part II 之 nonlocal语句

在下面的例子中taster返回函数nested,以备之后调用。对变量state的搜索符合通常的变量搜索规则。

>>> def tester(start):
...     state = start
...     def nested(label):
...         print(label, state)
...     return nested
... 
>>> F = tester(0)
>>> F('spam')
spam 0
>>> F('ham')
ham 0

默认情况下被嵌套的函数不能够对闭包函数内变量改变:

>>> def tester(start):
...     state = start
...     def nested(label):
...         print(label, state)
...         state += 1
...     return nested
... 
>>> F = tester(0)
>>> F('spam')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 4, in nested
UnboundLocalError: local variable 'state' referenced before assignment

使用nonlocal改变变量

>>> def tester(start):
...     state = start
...     def nested(label):
...         nonlocal state
...         print(label, state)
...         state += 1
...     return nested
... 
>>> F = tester(0)
>>> F('spam')
spam 0
>>> F('ham')    #state可以累加
ham 1
>>> F('eggs')
eggs 2

就像通常的闭包函数的引用,我们调用tester多少次就会在内存中有对少个state的拷贝。闭包作用域中的state对象是和函数返回的nested函数对象相捆绑的。每次调用就会产生一个完全不同的state对象,例如更新一个函数的state并不会影响另一个,下面的例子可以解释:

>>> G = tester(42)
>>> G('spam')
spam 42
>>> G('eggs')
eggs 43
>>> F('bacon')
bacon 3

边界情况

尽管nonlocal十分有用,但有一些情况必须事先知道。首先,不像global,nonlocal声明的变量必须事先赋值,否则会抛出错误:

>>> def tester(start):
...     def nested(label):
...         nonlocal state
...         state = 0
...         print(label, state)
...     return nested
... 
  File "<stdin>", line 3
SyntaxError: no binding for nonlocal 'state' found
>>> def tester(start):
...     def nested(label):
...         global state
...         state = 0
...         print(label, state)
...     return nested
... 
>>> F = tester(0)
>>> F('abc')
abc 0
>>> state
0

其次,nonlocal限制作用域只在闭包函数中寻找。nonlocal不会往上在模块的全局作用域或者函数之外的Python内置作用域:

>>> spam = 99
>>> def tester():
...     def nested():
...         nonlocal spam
...         print('Current=', spam)
...         spam += 1
...     return nested
... 
  File "<stdin>", line 3
SyntaxError: no binding for nonlocal 'spam' found
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值