在Python 2中,如何写入父作用域中的变量?
我有一些代码,例如:
def example():
# other logic omitted
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)
# more logic...
向 stored_blocks
添加元素效果很好,但我无法在第二个嵌套函数中增加 num_converted
。我收到一个异常,内容为UnboundLocalError:赋值前引用的局部变量“num_converted”
。
我知道在 3.x 中,我可以尝试 nonlocal num_converted
,但是如何解决 2.x 中的问题?我不想为此使用全局变量。
I have some code like:
def example():
# other logic omitted
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)
# more logic...
Adding elements to stored_blocks
works fine, but I cannot increase num_converted
in the second nested function. I get an exception that says UnboundLocalError: local variable 'num_converted' referenced before assignment
.
I know that in 3.x, I could try nonlocal num_converted
, but how can I solve the problem in 2.x? I don't want to use a global variable for this.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
问题:这是因为Python的作用域规则是疯狂的。
+=
赋值运算符的存在将目标num_converted
标记为封闭函数作用域的本地目标,并且在 Python 2.x 中没有可靠的方法来访问从那里开始一个范围界定级别。只有global
关键字可以将变量引用提升到当前范围之外,并且它可以将您直接带到顶部。修复:将
num_converted
转换为单元素数组。Problem: This is because Python's scoping rules are demented. The presence of the
+=
assignment operator marks the target,num_converted
, as local to the enclosing function's scope, and there is no sound way in Python 2.x to access just one scoping level out from there. Only theglobal
keyword can lift variable references out of the current scope, and it takes you straight to the top.Fix: Turn
num_converted
into a single-element array.(请参阅下面的编辑答案)
您可以使用类似的东西:
这样,
num_converted
作为convert_variable方法的类似C的“静态”变量(已编辑)
这样,您不需要在主程序中初始化计数器。
(see below for the edited answer)
You can use something like:
This way,
num_converted
works as a C-like "static" variable of the convert_variable method(edited)
This way, you don't need to initialize the counter in the main procedure.
使用
global
关键字就可以了。如果你写:...
num_converted
不会成为“全局变量”(即它不会在任何其他意想不到的地方变得可见),它只是意味着它可以在内部修改转换变量。这似乎正是你想要的。
换句话说,
num_converted
已经是一个全局变量。global num_converted
语法所做的一切就是告诉 Python“在这个函数内,不要创建本地num_converted
变量,而是使用现有的全局变量。Using the
global
keyword is fine. If you write:...
num_converted
doesn't become a "global variable" (i.e. it doesn't become visible in any other unexpected places), it just means it can be modified insideconvert_variables
. That seems to be exactly what you want.To put it another way,
num_converted
is already a global variable. All theglobal num_converted
syntax does is tell Python "inside this function, don't create a localnum_converted
variable, instead, use the existing global one.使用类实例来保存状态怎么样?
您实例化一个类并将实例方法传递给 subs,这些函数将引用 self...
What about using a class instance to hold the state?
You instantiate a class and pass instance methods to subs and those functions would have a reference to self...
我有几句话。
首先,在处理原始回调时会出现此类嵌套函数的一个应用程序,如 xml.parsers.expat 等库中所使用的那样。 (库作者选择这种方法可能会令人反感,但是......尽管如此,还是有使用它的理由。)
第二:在类中,有比数组(num_converted[0])更好的替代方案。我想这就是 Sebastjan 所说的。
它仍然很奇怪,值得在代码中发表评论......
但该变量至少是类的本地变量。
I have couple of remarks.
First, one application for such nested functions comes up when dealing with raw callbacks, as are used in libraries like xml.parsers.expat. (That the library authors chose this approach may be objectionable, but ... there are reasons to use it nonetheless.)
Second: within a class, there are much nicer alternatives to the array (num_converted[0]). I suppose this is what Sebastjan was talking about.
It's still odd enough to merit a comment in the code...
But the variable is at least local to the class.
修改自:https://stackoverflow.com/a/40690954/819544
您可以利用
检查 模块来访问调用范围的全局字典并写入其中。这意味着甚至可以利用此技巧从导入的子模块中定义的嵌套函数访问调用范围。
根据需要使用
scope_level
参数。设置scope_level=1
适用于子模块中定义的函数,scope_level=2
适用于子模块中的装饰器中定义的内部函数,等等。注意:只是因为您 < em>可以这样做,并不意味着你应该这样做。
Modified from: https://stackoverflow.com/a/40690954/819544
You can leverage the
inspect
module to access the calling scope's globals dict and write into that. That means this trick can even be leveraged to access the calling scope from a nested function defined in an imported submodule.Play with the
scope_level
argument as needed. Settingscope_level=1
works for a function defined in a submodule,scope_level=2
for the inner function defined in a decorator in a submodule, etc.NB: Just because you can do this, doesn't mean you should.