重构以消除递归函数中的全局变量 [英] Refactoring to eliminate global variable in recursive function

查看:90
本文介绍了重构以消除递归函数中的全局变量的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用来自 SO 问题的函数从文本文件输入中创建树结构:Python 文件解析:从文本构建树文件.但是我只能通过使用全局变量来生成我的树,并且找不到避免这种情况的方法.

I am creating a tree structure out of a text file input using a function from SO question: Python file parsing: Build tree from text file. But I am able to produce my tree only by using a global variable and cannot find a way of avoiding this.

在名为 data.txt 的文件中,我有以下内容:

In a file called data.txt I have the following:

Root
-A 10
-B
--B A 2
--B B 5
--B Z 9
--B X
---X 4
---Y
----Y0 67
----Y1 32
---Z 3
-C 19

想要的结果

{'B': ['B A 2', 'B B 5', 'B Z 9', 'B X'],
 'B X': ['X 4', 'Y', 'Z 3'],
 'Root': ['A 10', 'B', 'C 19'],
 'Y': ['Y0 67', 'Y1 32']}

我的代码

import re, pprint
PATTERN = re.compile('^[-]+')
tree = {}

def _recurse_tree(parent, depth, source):
    last_line = source.readline().rstrip()
    while last_line:
        if last_line.startswith('-'):
            tabs = len( re.match(PATTERN, last_line).group() )
        else:
            tabs = 0
        if tabs < depth:
            break
        node = re.sub(PATTERN, '', last_line.strip())
        if tabs >= depth:
            if parent is not None:
                print "%s: %s" %(parent, node)
                if parent in tree:
                    tree[parent].append(node)
                else:
                    tree[parent] = [ node, ]
            last_line = _recurse_tree(node, tabs+1, source)
    return last_line

def main():
    inFile = open("data.txt")
    _recurse_tree(None, 0, inFile)
    pprint.pprint(tree)

if __name__ == "__main__":
    main()

问题

如何去掉全局变量tree?我所做的一切似乎都让代码变得更长或更难看,但我想大量使用该函数,而且我讨厌依赖于核心结果的副作用.

The Problem

How do I get rid of the global variable tree? Everything I do seems to make the code much longer or uglier but I would like to use the function heavily and I hate depending on side-effects for the core result.

在下面的答案之后,我修改了代码以按以下方式返回tree.这是蟒蛇吗?返回一个元组然后抛出第一个元素似乎不雅.

After the answers below, I revised the code to return the tree in the following way. Is this pythonic? Returning a tuple and then tossing the first element seems inelegant.

def _recurse_tree(parent, depth, source, tree=None):
    if tree is None:
        tree = {}
    last_line = source.readline().rstrip()
    while last_line:
        if last_line.startswith('-'):
            tabs = len( re.match(PATTERN, last_line).group() )
        else:
            tabs = 0
        if tabs < depth:
            break
        node = re.sub(PATTERN, '', last_line.strip())
        if tabs >= depth:
            if parent is not None:
                print "%s: %s" %(parent, node)
                if parent in tree:
                    tree[parent].append(node)
                else:
                    tree[parent] = [ node, ]
            last_line, tree = _recurse_tree(node, tabs+1, source, tree)
    return last_line, tree

def main():
    inFile = open("data.txt")
    tmp, tree = _recurse_tree(None, 0, inFile)
    pprint.pprint(tree)

推荐答案

你的 tree 变量已经是可变的;只需将它与您的递归调用一起传递:

Your tree variable is already a mutable; just pass it along with your recursive calls:

def _recurse_tree(parent, depth, source, tree=None):
    if tree is None:
        tree = {}

    last_line = source.readline().rstrip()
    while last_line:
        if last_line.startswith('-'):
            tabs = len( re.match(PATTERN, last_line).group() )
        else:
            tabs = 0
        if tabs < depth:
            break
        node = re.sub(PATTERN, '', last_line.strip())
        if tabs >= depth:
            if parent is not None:
                print "%s: %s" %(parent, node)
                if parent in tree:
                    tree[parent].append(node)
                else:
                    tree[parent] = [ node, ]
            last_line = _recurse_tree(node, tabs+1, source, tree)
    return last_line

或者,您可以使用类来保存状态,然后从实例中提取状态会更容易:

Alternatively, you can use a class to hold the state, it'll be easier to then pluck the state from the instance:

class TreeBuilder(object):
    _PATTERN = re.compile('^[-]+')

    def __init__(self, source):
        self.tree = {}
        self.source = source
        self._recurse_tree()

    def _recurse_tree(self, parent=None, depth=0):
         last_line = self.source.readline().rstrip()
         while last_line:
             if last_line.startswith('-'):
                 tabs = len( self._PATTERN.match(last_line).group() )
             else:
                 tabs = 0
             if tabs < depth:
                 break
             node = self._PATTERN.sub('', last_line.strip())
             if tabs >= depth:
                 if parent is not None:
                     print "%s: %s" %(parent, node)
                     if parent in self.tree:
                         self.tree[parent].append(node)
                     else:
                         self.tree[parent] = [ node, ]
                 last_line = self._recurse_tree(node, tabs+1)
         return last_line

然后像这样使用它:

def main():
    inFile = open("data.txt")
    builder = TreeBuilder(inFile)
    pprint.pprint(builder.tree)

这篇关于重构以消除递归函数中的全局变量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆