Python递归中的变量作用域错误
下面的代码是用递归的方式处理一个字典列表,把它变成一个树形结构,同时生成一个HTML输出字符串。当我在递归函数中尝试访问output
这个字符串变量时,出现了作用域访问错误。不过,它可以正常访问同一作用域中的nodes
列表对象。实际上,在我添加output
变量之前,这个函数是可以正常工作的。这是怎么回事呢?
nodes = [
{ 'id':1, 'parent_id':None, 'name':'a' },
{ 'id':2, 'parent_id':None, 'name':'b' },
{ 'id':3, 'parent_id':2, 'name':'c' },
{ 'id':4, 'parent_id':2, 'name':'d' },
{ 'id':5, 'parent_id':4, 'name':'e' },
{ 'id':6, 'parent_id':None, 'name':'f' }
]
output = ''
def build_node(node):
output += '<li><a>'+node['name']+'</a>'
subnodes = [subnode for subnode in nodes if subnode['parent_id'] == node['id']]
if len(subnodes) > 0 :
output += '<ul>'
[build_node(subnode) for subnode in subnodes]
output += '</ul>'
output += '</li>'
return node
output += '<ul>'
node_tree = [build_node(node) for node in nodes if node['parent_id'] == None]
output += '</ul>'
import pprint
pprint.pprint(node_tree)
错误:
Traceback (most recent call last):
File "prog.py", line 23, in <module>
node_tree = [build_node(node) for node in nodes if node['parent_id'] == None]
File "prog.py", line 13, in build_node
output += '<li><a>'+node['name']+'</a>'
UnboundLocalError: local variable 'output' referenced before assignment
3 个回答
在编程中,有时候我们需要处理一些数据,比如从一个地方获取数据,然后在另一个地方使用这些数据。这个过程就像是把水从一个桶倒到另一个桶一样。
有些时候,我们会遇到一些问题,比如数据的格式不对,或者数据不完整。这就像是你在倒水的时候,发现桶里有个洞,水流不进去一样。
为了避免这些问题,我们可以使用一些工具和方法来检查和处理数据。这样可以确保我们得到的数据是正确的,能够顺利地使用。
总之,处理数据就像是一个搬运工,需要小心翼翼地确保每一步都做对,才能最终把数据安全地送到目的地。
def build_node(node):
global output
# proceed as before
虽然你可以使用 global
声明,但把 output
作为参数传递会更清晰。
全局变量被认为是不好的编程习惯,如果有好的方法可以避免使用它们,你应该尽量使用这些方法。
这个错误是因为:
output = ''
def add(s):
output = output + s
这相当于 output+=s
。在展开的形式中,两个 output
指的是不同的范围。赋值操作创建了一个局部变量,而右边的表达式引用了一个全局变量(因为局部变量还没有被设置)。
Python 会检测到这种冲突并抛出错误。
其他人建议使用 global
来告诉 Python 两个 output
都指向全局范围,但因为你在这里是拼接字符串,其实有一个更好的方法可以用在 Python 中:
output_list = []
def add(s):
output_list.append(s)
# ...
output = ''.join(output_list)
在这里,你并没有在函数中设置一个变量,所以不需要使用 global
。所有调用的字符串都被添加到一个列表中,最后用 ''
(空字符串)作为分隔符连接起来。这种方法比用 +=
拼接字符串要快得多,因为在 Python 中,字符串是不可变的,所以每次你拼接两个字符串时,Python 都需要创建一个新的字符串。这会导致大量的内存复制。