这个类是一个递归调用自身(self.next()
)的生成器。
这有点奇怪,因为当您向生成器询问其所有值时,它并没有像您期望的那样通过返回self
(具有函数的对象)来真正遵循迭代协议。.next()
相反,它返回 的结果self.next()
,这是相当糟糕的措辞。该next
函数应该只是被调用permutations()
,因为该函数实际上与迭代协议中需要next
一个函数这一事实没有任何关系。next
无论如何,如果您使用递归深度参数扩充函数,您可以看到它的递归跟踪:
class Permutation:
def __init__(self,justalist):
self._data = justalist[:]
self._sofar = []
def __iter__(self):
return self.next()
def next(self, depth=0):
debug = lambda text:print('\t'*depth+' '+text)
for elem in self._data:
#print( 'self._data: {}'.format(self._data) )
#print( 'self._sofar: {}'.format(self._sofar) )
if elem not in self._sofar:
self._sofar.append(elem)
if len(self._sofar) == len(self._data):
debug( 'yielding self._sofar[:]: {}'.format(self._sofar[:]) )
yield self._sofar[:]
else:
for v in self.next(depth+1):
debug( 'yielding elements of self.next() one-by-one: {}'.format(v) )
yield v
self._sofar.pop()
演示:
>>> list( Permutation(range(4)) )
yielding self._sofar[:]: [0, 1, 2, 3]
yielding elements of self.next() one-by-one: [0, 1, 2, 3]
yielding elements of self.next() one-by-one: [0, 1, 2, 3]
yielding elements of self.next() one-by-one: [0, 1, 2, 3]
yielding self._sofar[:]: [0, 1, 3, 2]
yielding elements of self.next() one-by-one: [0, 1, 3, 2]
yielding elements of self.next() one-by-one: [0, 1, 3, 2]
yielding elements of self.next() one-by-one: [0, 1, 3, 2]
yielding self._sofar[:]: [0, 2, 1, 3]
yielding elements of self.next() one-by-one: [0, 2, 1, 3]
yielding elements of self.next() one-by-one: [0, 2, 1, 3]
yielding elements of self.next() one-by-one: [0, 2, 1, 3]
yielding self._sofar[:]: [0, 2, 3, 1]
yielding elements of self.next() one-by-one: [0, 2, 3, 1]
yielding elements of self.next() one-by-one: [0, 2, 3, 1]
yielding elements of self.next() one-by-one: [0, 2, 3, 1]
yielding self._sofar[:]: [0, 3, 1, 2]
yielding elements of self.next() one-by-one: [0, 3, 1, 2]
yielding elements of self.next() one-by-one: [0, 3, 1, 2]
yielding elements of self.next() one-by-one: [0, 3, 1, 2]
yielding self._sofar[:]: [0, 3, 2, 1]
yielding elements of self.next() one-by-one: [0, 3, 2, 1]
yielding elements of self.next() one-by-one: [0, 3, 2, 1]
yielding elements of self.next() one-by-one: [0, 3, 2, 1]
yielding self._sofar[:]: [1, 0, 2, 3]
yielding elements of self.next() one-by-one: [1, 0, 2, 3]
yielding elements of self.next() one-by-one: [1, 0, 2, 3]
yielding elements of self.next() one-by-one: [1, 0, 2, 3]
如您所见,数据流如下:递归进行到最深的级别(在本例中为 4,len([0,1,2,3])
即 4),产生一个排列,并将其返回到前一个级别。该级别将其返回到之前的级别,依此类推。在最高级别,收益率将其返回。
总之,这是一个破碎而糟糕的实现,因为:
- 它可以通过带有这个额外的类废话的递归函数模式来完成
- 它
next()
以一种强烈暗示某事的方式定义,但实际上做了其他事情。
- 如果任何值重复,它将失败,例如
Permutation([0,1,1])
将失败
你应该只使用http://docs.python.org/library/itertools.html#itertools.permutations ( from itertools import permutations
)