Python中递归期间的变量范围错误

时间:2011-11-20 15:28:33

标签: python recursion scope

以下代码在构建HTML输出字符串时以递归方式将字典列表处理为树。尝试从递归函数中访问output字符串变量时,我收到范围访问错误。但是,在同一范围内访问nodes列表对象没有问题 - 事实上,在添加output var之前,函数工作正常。这是什么交易?

样品: http://ideone.com/Kg8ti

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 个答案:

答案 0 :(得分:3)

错误源于此:

output = ''
def add(s):
    output = output + s

相当于output+=s。扩展形式中的两个output - s指的是不同的范围。赋值设置局部变量,而右边的表达式引用全局(因为尚未设置本地)。

Python检测到此类冲突并引发错误。

其他人建议使用global让Python知道两个output - s引用全局范围,但由于你在这里连接字符串,所以在Python中使用这个任务有更好的习惯用法:

output_list = []
def add(s):
    output_list.append(s)
# ...
output = ''.join(output_list)

这里你没有在函数中设置变量,因此不需要global。来自所有调用的字符串将添加到列表中,最后使用''(空字符串)作为分隔符进行连接。这比使用+=添加字符串要快得多,因为Python中的字符串是不可变的,因此每次添加两个字符串时,Python都必须创建一个新字符串。这引入了大量的内存复制。

答案 1 :(得分:1)

def build_node(node):
    global output
    # proceed as before

答案 2 :(得分:1)

虽然您可以使用global声明,但将output作为参数传递会更加清晰。

Global variables are considered to bad practice如果有避免使用它们的好方法,你应该利用这些方法。