原因:
因为对象的精髓就在于组合(composition)与对象构造(object construction)。
对象需要有组合成分构成,而且得以某种方式初始化。这里也涉及到递归和生成器(generator)的使用。
生成器是很棒的数据类型。你可以只通过构造一个很长的列表,然后打印列表的内容,就可以取得与print_all_2类似的功能。生成器还有一个好处,就是不用占据很多内存。
有一点还值得指出,就是print_all_1会以深度优先(depth-first)的方式遍历树(tree),而print_all_2则是宽度优先(width-first)。有时候,一种遍历方式比另一种更合适。但这要看你的应用的具体情况。
# coding=utf-8
class Node(object):
def __init__(self, sName, tmp=None):
self._lChildren = []
self.sName = sName
self.tmp = tmp
def __repr__(self):
return "{}<Node '{}'>".format(self.tmp, self.sName)
def append(self, *args, **kwargs):
self._lChildren.append(*args, **kwargs)
# 以深度优先(depth-first)的方式遍历树(tree)
def print_all_1(self):
print(self)
for oChild in self._lChildren:
oChild.print_all_1( )
# 宽度优先(width-first)
def print_all_2(self):
def gen(o):
lAll = [o, ]
while lAll:
oNext = lAll.pop(0)
lAll.extend(oNext._lChildren)
yield oNext # 生成器
for oNode in gen(self):
print(oNode)
oRoot = Node("root")
oChild1 = Node("child1", "\t")
oChild2 = Node("child2", "\t")
oChild3 = Node("child3", "\t")
oChild4 = Node("child4", "\t\t")
oChild5 = Node("child5", "\t\t")
oChild6 = Node("child6", "\t\t")
oChild7 = Node("child7", "\t\t\t")
oChild8 = Node("child8", "\t\t")
oChild9 = Node("child9", "\t\t")
oChild10 = Node("child10", "\t\t\t")
oRoot.append(oChild1)
oRoot.append(oChild2)
oRoot.append(oChild3)
oChild1.append(oChild4)
oChild1.append(oChild5)
oChild2.append(oChild6)
oChild3.append(oChild8)
oChild3.append(oChild9)
oChild4.append(oChild7)
oChild6.append(oChild10)
# 从后往前看顺序
oRoot.print_all_1( )
# 输出:
"""
None<Node 'root'>
<Node 'child1'>
<Node 'child4'>
<Node 'child7'>
<Node 'child5'>
<Node 'child2'>
<Node 'child6'>
<Node 'child10'>
<Node 'child3'>
<Node 'child8'>
<Node 'child9'>
"""
# 从前往后看顺序
oRoot.print_all_2( )
# 输出:
"""
None<Node 'root'>
<Node 'child1'>
<Node 'child2'>
<Node 'child3'>
<Node 'child4'>
<Node 'child5'>
<Node 'child6'>
<Node 'child8'>
<Node 'child9'>
<Node 'child7'>
<Node 'child10'>
"""