Pythonclosures:写入父范围的variables
我有一个函数内的以下代码:
stored_blocks = {} def replace_blocks(m): block = m.group(0) block_hash = sha1(block) stored_blocks[block_hash] = block return '{{{%s}}}' % block_hash num_converted = 0 def convert_variables(m): name = m.group(1) num_converted += 1 return '<%%= %s %%>' % name fixed = MATCH_DECLARE_NEW.sub('', template) fixed = MATCH_PYTHON_BLOCK.sub(replace_blocks, fixed) fixed = MATCH_FORMAT.sub(convert_variables, fixed)
将要素添加到stored_blocks
工作正常,但我不能增加num_converted
在第二num_converted
function:
UnboundLocalError:分配之前引用的局部variables“num_converted”
我可以使用global
variables但是全局variables很难看,我真的不需要这个variables是全局的。
所以我很好奇我如何写入父函数作用域中的variables。 nonlocal num_converted
可能会完成这项工作,但是我需要一个可以与Python 2.x nonlocal num_converted
工作的解决scheme。
问题:这是因为Python的范围规则是疯狂的。 +=
赋值运算符的存在将目标文件num_converted
标记为封闭函数作用域的本地对象,在Python 2.x中没有任何声音方式只能从那里访问一个范围级别。 只有global
关键字才能将可变引用从当前作用域中提取出来,并将其直接引导到顶端。
修复:将num_converted
转换为单个元素的数组。
num_converted = [0] def convert_variables(m): name = m.group(1) num_converted[0] += 1 return '<%%= %s %%>' % name
(请参阅下面的编辑答案)
你可以使用像这样的东西:
def convert_variables(m): name = m.group(1) convert_variables.num_converted += 1 return '<%%= %s %%>' % name convert_variables.num_converted = 0
这样, num_converted
就像convert_variable方法的类似C的“静态”variables一样工作
(编辑)的
def convert_variables(m): name = m.group(1) convert_variables.num_converted = convert_variables.__dict__.get("num_converted", 0) + 1 return '<%%= %s %%>' % name
这样,你不需要在主程序中初始化计数器。
使用global
关键字是好的。 如果你写:
num_converted = 0 def convert_variables(m): global num_converted name = m.group(1) num_converted += 1 return '<%%= %s %%>' % name
… num_converted
不会成为一个“全局variables”(即它不会在任何其他意想不到的地方变得可见),它只是意味着它可以在convert_variables
修改。 这似乎正是你想要的。
换句话说, num_converted
已经是一个全局variables。 所有global num_converted
语法的作用是告诉Python“在这个函数内部,不要创build一个本地的num_converted
variables,而是使用现有的全局variables。
那么使用类实例来保存状态呢? 你实例化一个类,并将实例方法传递给subs,这些函数将有一个引用自我…
我有几句话
首先,在处理原始callback函数时会出现一个这样的嵌套函数的应用程序,就像xml.parsers.expat这样的库中使用的那样。 (图书馆作者select这种方法可能是令人反感的,但是……仍有理由使用它。)
第二:在一个类中,有更好的替代数组(num_converted [0])。 我想这就是塞巴斯蒂安正在谈论的。
class MainClass: _num_converted = 0 def outer_method( self ): def convert_variables(m): name = m.group(1) self._num_converted += 1 return '<%%= %s %%>' % name
在代码中值得评论还是很古怪的……但是这个variables至less是本地的。