발전기에 peek
,, hasNext
등의 품목이없는 경우 간단한 테스트 방법이 isEmpty
있습니까?
답변
귀하의 질문에 대한 간단한 답변 : 아니오, 간단한 방법은 없습니다. 해결 방법이 많이 있습니다.
생성기가 무엇인지에 따라 간단한 방법이 없어야 합니다 . 시퀀스를 메모리에 유지하지 않고 일련의 값을 출력하는 방법 . 따라서 뒤로 순회가 없습니다.
원하는 경우 has_next 함수를 작성하거나 멋진 데코레이터로 메소드로 생성기에 쓸 수도 있습니다.
답변
암시:
def peek(iterable):
try:
first = next(iterable)
except StopIteration:
return None
return first, itertools.chain([first], iterable)
용법:
res = peek(mysequence)
if res is None:
# sequence is empty. Do stuff.
else:
first, mysequence = res
# Do something with first, maybe?
# Then iterate over the sequence:
for element in mysequence:
# etc.
답변
간단한 방법은 생성기가 소진되거나 비어있는 경우 next ()에 선택적 매개 변수를 사용하는 것입니다. 예를 들면 다음과 같습니다.
iterable = some_generator()
_exhausted = object()
if next(iterable, _exhausted) == _exhausted:
print('generator is empty')
편집 : mehtunguh의 의견에서 지적 된 문제가 수정되었습니다.
답변
next(generator, None) is not None
또는 대체 None
하지만 당신이 알고있는 값 은 발전기에 없습니다 .
편집 : 예, 생성기에서 1 개의 항목을 건너 뜁니다. 그러나 종종 유효성 검사 목적으로 만 생성기가 비어 있는지 확인한 다음 실제로 사용하지는 않습니다. 그렇지 않으면 나는 다음과 같은 것을한다 :
def foo(self):
if next(self.my_generator(), None) is None:
raise Exception("Not initiated")
for x in self.my_generator():
...
그게 당신의 경우이 작품이며, 발전기는 A로부터 오는 기능 처럼 generator()
.
답변
IMHO의 최선의 방법은 특별한 테스트를 피하는 것입니다. 대부분의 시간, 발전기의 사용 이다 테스트는 :
thing_generated = False
# Nothing is lost here. if nothing is generated,
# the for block is not executed. Often, that's the only check
# you need to do. This can be done in the course of doing
# the work you wanted to do anyway on the generated output.
for thing in my_generator():
thing_generated = True
do_work(thing)
충분하지 않은 경우에도 명시 적 테스트를 수행 할 수 있습니다. 이 시점 thing
에서 마지막으로 생성 된 값이 포함됩니다. 아무것도 생성되지 않은 경우 변수를 아직 정의하지 않은 경우 정의되지 않습니다. 의 값을 확인할 수 thing
있지만 약간 신뢰할 수 없습니다. 대신 블록 내에 플래그를 설정하고 나중에 확인하십시오.
if not thing_generated:
print "Avast, ye scurvy dog!"
답변
나는 나 자신을 사용하지 않을 것이라고, 특히 한 두 번째 솔루션을 제공 싫지만, 당신은 절대적 경우 한 이 작업을 수행하고 다른 답변에서와 같이 발전기를 소비하지 :
def do_something_with_item(item):
print item
empty_marker = object()
try:
first_item = my_generator.next()
except StopIteration:
print 'The generator was empty'
first_item = empty_marker
if first_item is not empty_marker:
do_something_with_item(first_item)
for item in my_generator:
do_something_with_item(item)
이제는이 솔루션이 마음에 들지 않습니다. 왜냐하면 이것이 발전기가 사용되는 방식이 아니라고 믿기 때문입니다.
답변
나는이 게시물이 지금 5 세라는 것을 알고 있지만, 이것을하는 관용적 인 방법을 찾고있는 동안 그것을 발견했지만 내 솔루션이 게시되지 않았습니다. 후손을 위해 :
import itertools
def get_generator():
"""
Returns (bool, generator) where bool is true iff the generator is not empty.
"""
gen = (i for i in [0, 1, 2, 3, 4])
a, b = itertools.tee(gen)
try:
a.next()
except StopIteration:
return (False, b)
return (True, b)
물론, 많은 주석가들이 지적 하겠지만, 이것은 해키이며 특정 제한된 상황 (예 : 발전기가 부작용이없는 곳)에서만 작동합니다. YMMV.