重构以消除递归函数中的全局变量 [英] Refactoring to eliminate global variable in recursive function
问题描述
我正在使用来自 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屋!