関数が定義済みの値を返すまで、関数を繰り返し呼び出してリストを生成したいと思います。
myList = [i,r = foo() while i==0]
myList = [r1, r2, r3, r4...] as long as returned i value is == 0
リスト内包表記を使用してこれを行う方法はありますか?
関数が定義済みの値を返すまで、関数を繰り返し呼び出してリストを生成したいと思います。
myList = [i,r = foo() while i==0]
myList = [r1, r2, r3, r4...] as long as returned i value is == 0
リスト内包表記を使用してこれを行う方法はありますか?
def stop_iteration():
raise StopIteration
foo()
がジェネレーターの場合:
myList = list((i,r) if i != 0 else stop_iteration() for (i,r) in foo())
そうしないと:
def foo_generator():
i,r = foo()
while i != 0:
yield i,r
i,r = foo()
myList = list(foo_generator())
いいえ、それはできません。リスト内包表記がサポートする唯一のキーワードは、、、for
およびif
(else
そしてlambda
もちろん) です。
したがって、複数行のソリューションを実行する必要があります。ただし、ラッパー関数を定義する必要はありません。これはうまくいきます:
mylist = []
while True:
i, r = foo()
if i: break
mylist.append(r)
最後に、mylist
あなたが望むすべてのものを手に入れます。
そのためのワンライナーはないと思います。ただし、特定のfoo
-like 関数をラップする単純なジェネレーターを定義することで、それを行うことができます。
TEST = [(0, 0), (1, 0), (2, 1), (3, 0)]
def foo():
return TEST.pop(0)
def foo_wrapper(foo_like):
r, i = foo_like()
while i == 0:
yield r
r, i = foo_like()
print list(foo_wrapper(foo))
これはお勧めできませんが...
>>> def notyet(predicate):
if predicate:
raise StopIteration
return True
>>> # note that below we're wrapping a generator expression in a
>>> # call to `list` so that when `StopIteration` is raised your
>>> # program won't terminate.
>>> xs = list((i, r) for (i, r) in foo() if notyet(i!=0))
>>> # if we try this instead, your program will hit the buffers
>>> # when the predicate is satisfied.
>>> xs = [(i, r) for (i, r) in foo() if notyet(i!=0)]
Traceback (most recent call last):
File "<pyshell#5>", line 1, in <module>
xs = [(i, r) for (i, r) in foo() if notyet(i!=0)]
File "<pyshell#3>", line 3, in notyet
raise StopIteration
StopIteration
この状況では、itertools.takewhile を使用する方がはるかに優れています。
>>> from itertools import takewhile
>>> xs = list(takewhile(lambda (i, r): i!=0, foo()))