In Python 2, how do I write to variable in the parent scope?
我在函数中有以下代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | 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) |
在
UnboundLocalError: local variable 'num_converted' referenced before assignment
我可以使用
所以我很好奇,我怎么能写一个父函数范围内的变量。
问题:这是因为python的作用域规则是疯狂的。
修正:把
1 2 3 4 5 | num_converted = [0] def convert_variables(m): name = m.group(1) num_converted[0] += 1 return '<%%= %s %%>' % name |
(编辑后的答案见下文)
您可以使用如下内容:
1 2 3 4 5 6 | def convert_variables(m): name = m.group(1) convert_variables.num_converted += 1 return '<%%= %s %%>' % name convert_variables.num_converted = 0 |
这样,
(编辑)
1 2 3 4 | def convert_variables(m): name = m.group(1) convert_variables.num_converted = convert_variables.__dict__.get("num_converted", 0) + 1 return '<%%= %s %%>' % name |
这样,您就不需要在主过程中初始化计数器。
使用
1 2 3 4 5 6 | num_converted = 0 def convert_variables(m): global num_converted name = m.group(1) num_converted += 1 return '<%%= %s %%>' % name |
…
换句话说,
使用类实例保存状态怎么样?您实例化一个类并将实例方法传递给subs,这些函数将具有对self的引用…
我有几句话。
首先,在处理原始回调时,会出现一个此类嵌套函数的应用程序,就像在xml.parsers.expat等库中使用的那样。(图书馆作者选择这种方法可能会令人反感,但……尽管如此,还是有理由使用它。)
第二:在一个类中,有许多更好的数组替代品(num_converted[0])。我想这就是塞巴斯坦所说的。
1 2 3 4 5 6 7 | class MainClass: _num_converted = 0 def outer_method( self ): def convert_variables(m): name = m.group(1) self._num_converted += 1 return '<%%= %s %%>' % name |
在代码中值得一个注释还是很奇怪的…但是变量至少是类的局部变量。
修改自:https://stackoverflow.com/a/40690954/819544
您可以利用
1 2 3 4 5 6 7 8 9 10 11 12 | import inspect def get_globals(scope_level=0): return dict(inspect.getmembers(inspect.stack()[scope_level][0]))["f_globals"] num_converted = 0 def foobar(): get_globals(0)['num_converted'] += 1 foobar() print(num_converted) # 1 |
根据需要使用
NB:仅仅因为你能做到这一点,并不意味着你应该做到。