[英]Need help understanding Python closures
我有这个代码:
import re
def doReplace(toReplace):
i = 1
def chapterReplacer(_):
result = 'Chapter %i' % i
i += 1
return result
return re.sub('Chapter [a-zA-Z]+', chapterReplacer, test)
test = 'Chapter one Chapter Two Chapter three'
print doReplace(test)
当我运行它时,我收到以下错误:
Traceback (most recent call last):
File "C:/Python26/replace.py", line 13, in <module>
print doReplace(test)
File "C:/Python26/replace.py", line 10, in doReplace
return re.sub('Chapter [a-zA-Z]+', chapterReplacer, test)
File "C:\Python26\lib\re.py", line 151, in sub
return _compile(pattern, 0).sub(repl, string, count)
File "C:/Python26/replace.py", line 6, in chapterReplacer
result = 'Chapter %i' % i
UnboundLocalError: local variable 'i' referenced before assignment
我的印象是chapterReplacer会捕获局部变量i,但这似乎没有发生?
不,并且在python 2中,你根本不能使用带有mutable的技巧:
def doReplace(toReplace):
i = [1]
def chapterReplacer(_):
result = 'Chapter %i' % i[0]
i[0] += 1
return result
return re.sub('Chapter [a-zA-Z]+', chapterReplacer, test)
通常情况下,如果变量未被分配到本地,则python将只查看变量的周围范围; 一旦bytecompiler看到直接赋值( i = something
)并且没有global i
语句来说服它,否则变量被认为是本地的。
但是在上面的代码中,我们从未在chapterReplacer
函数中分配给i
。 是的,我们确实改变了i[0]
但是存储在i
本身的值(列表)没有改变。
在python 3中,只需使用nonlocal
语句让python查看变量的闭包:
def doReplace(toReplace):
i = 1
def chapterReplacer(_):
nonlocal i
result = 'Chapter %i' % i
i += 1
return result
return re.sub('Chapter [a-zA-Z]+', chapterReplacer, test)
你可以让i
成为一个函数属性
def doReplace(toReplace):
chapterReplacer.i = 1
def chapterReplacer(_):
result = 'Chapter %i' % chapterReplacer.i
chapterReplacer.i += 1
return result
return re.sub('Chapter [a-zA-Z]+', chapterReplacer, test)
编辑:从python 3开始,你可以使用nonlocal
的@MartijnPieters解决方案。
在Python中,如果在函数内部赋值变量(即使使用复合赋值运算符,例如+=
),除非global
或非nonlocal
语句另有指定,否则该变量将被视为本地变量。
当编译器看到变量i
在函数chapterReplacer
得到另一个值时,它将它视为本地,并且不应用“闭合魔法”。 如果删除第i += 1
,您的代码将会运行。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.