使用递归函数时处理python全局变量

Jes*_*ose 3 python global-variables

我制作了一个从HTML文件中提取文本的程序.它递归HTML文档并返回标记列表.例如,

输入 <li>没办法<b>你</ b>正在这样做</ li>

输出 ['不','方式','你','是'...].

这是一个高度简化的伪代码:

def get_leaves(node):
    kids=getchildren(node)
    for i in kids:
        if leafnode(i):
            get_leaves(i)
        else:
            a=process_leaf(i)
            list_of_leaves.append(a)

def calling_fn():
    list_of_leaves=[] #which is now in global scope
    get_leaves(rootnode)
    print list_of_leaves    
Run Code Online (Sandbox Code Playgroud)

我现在在调用函数的全局范围内使用list_of_leaves.calling_fn()声明了这个变量,get_leaves()追加到这个变量.

我的问题是,如何修改我的函数,以便我能够执行类似list_of_leaves = get_leaves(rootnode)的操作,即不使用全局变量?

我不希望函数的每个实例都复制列表,因为列表可能会变得非常大.

请不要批评这个特定伪代码的设计,因为我简化了这一点.它用于另一个目的:使用BeautifulSoup提取令牌以及相关标签

Imr*_*ran 11

您可以将结果列表作为可选参数传递.

def get_leaves(node, list_of_leaves=None):
    list_of_leaves = [] if list_of_leaves is None else list_of_leaves
    kids=getchildren(node)
    for i in kids:
        if leafnode(i):
            get_leaves(i, list_of_leaves)
        else:
            a=process_leaf(i)
            list_of_leaves.append(a)

def calling_fn():
    result = [] 
    get_leaves(rootnode, list_of_leaves=result)
    print result
Run Code Online (Sandbox Code Playgroud)

Python对象总是通过引用传递.这种情况以前也讨论过这里.一些内置的类型是不可变的(例如int,string),所以你不能到位修改它们(当您连接两个字符串,并将其分配给一个变量,创建一个新的字符串).list可以修改可变类型(例如)的实例.我们通过将原始列表传递给我们的递归调用来利用这个优势.

为了在真实应用程序中从HTML中提取文本,使用成熟的库,BeautifulSoup或者lxml.html总是一个更好的选择(正如其他人所建议的那样).

  • 我认为你最好使用:如果list_of_leaves是None:list_of_leaves = [].例如代码:x = []; a = x或'test'(将测试分配给a).这意味着结果列表(在调用函数中)仍然是空的,你填充的是方法'get_leaves'中的单独列表 (2认同)

pil*_*her 8

如果get_leaves()转换为生成器,则无需将累加器传递给函数或通过全局名称访问它:

def get_leaves(node):
    for child in getchildren(node):
        if leafnode(child):
            for each in get_leaves(child):
                yield each
        else:
            yield process_leaf(child)

def calling_fn():
    list_of_leaves = list(get_leaves(rootnode))
    print list_of_leaves
Run Code Online (Sandbox Code Playgroud)