Python 3 -- [s for s in 子集(S)] 和 yield
这是我在网上找到的一段代码,但它没有太多解释。我只是想知道它是怎么工作的。我对yield
和[s for s in subsets(S)]
这部分不是很理解。任何见解都非常感谢!
def subsets(aList):
if aList ==[]: # base case
yield []
else:
first = aList[0]
rest = aList[1:]
for ss in subsets(rest): # include first or don't in each
yield ss # subset of rest
yield [first]+ss
print ("\n testing subsets")
S = ['A','B','C','D','E']
ss = [s for s in subsets(S)]
print ("The subsets of",S,"are:")
print (ss)
2 个回答
2
要理解 yield
,可以把它想象成一个返回语句,但有个特别之处就是,下次调用这个函数时,会从 yield
语句的地方继续执行。当没有更多的 yield
了,就会抛出一个 StopIteration
的异常。
下面是一个更简单的例子,可以帮助你理解:
>>> def foo():
... for i in range(3):
... yield i
...
>>> x = foo()
>>> x
<generator object foo at 0x7f0cd5c30780>
>>> x.next()
0
>>> x.next()
1
>>> x.next()
2
>>> x.next()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
>>>
你可以把生成器当作一个可迭代的对象来使用,因为 for
循环会自动捕捉并处理那个 StopIteration
异常:
>>> x = foo()
>>> for i in x:
... print i
...
0
1
2
>>>
至于获取子集,有更简单的方法!
看看下面的做法:
>>> from itertools import chain, combinations
>>>
>>> def powerset(iterable):
... s = list(iterable)
... return chain.from_iterable(combinations(s, r) for r in range(len(s)+1))
>>>
>>> S = ['A','B','C']
>>> list(powerset(S))
[(),
('A',),
('B',),
('C',),
('A', 'B'),
('A', 'C'),
('B', 'C'),
('A', 'B', 'C')]
4
subsets
是一个生成器:当你调用它的时候,它会创建一个可以逐个取值的对象。每当你从这个对象请求下一个值时,它就会运行到下一个 yield
语句,并生成那个值。它还是递归的,所以当你用五个项目运行它时,它会对最后四个项目自己调用自己,依此类推。
举个例子,如果传入 ['A']
,它会创建一个第二个生成器,并传入一个空列表 []
。这个生成器只会返回一个空列表,然后结束。主生成器会接收到这个空列表,返回它(yield ss
),然后再返回 [first]+ss
,这时就是 ['A']
。最终结果是:[[], ['A']]
[s for s in subsets(S)]
是一个列表推导式。它的意思和下面的代码是一样的:
ss = []
for s in subsets(S)
ss.append(s)
在这个情况下,其实有点多余——你可以直接用 list(subsets(S))
来达到同样的效果。列表推导式通常用在你想对一组对象做某些操作,或者想过滤这些对象的时候。