[PYTHON] 처음부터 발전기가 비어 있는지 어떻게 알 수 있습니까?
PYTHON처음부터 발전기가 비어 있는지 어떻게 알 수 있습니까?
생성기에 peek, hasNext, isEmpty 등과 같은 항목이없는 경우 간단한 방법으로 테스트 할 수 있습니까?
해결법
-
==============================
1.귀하의 질문에 대한 간단한 대답 : 아니오, 간단한 방법이 없습니다. 해결 방법이 많이 있습니다.
귀하의 질문에 대한 간단한 대답 : 아니오, 간단한 방법이 없습니다. 해결 방법이 많이 있습니다.
생성기가 무엇인지 간단하기 때문에 간단한 방법이 있어서는 안됩니다. 시퀀스를 메모리에 보관하지 않고 값의 시퀀스를 출력하는 방법입니다. 따라서 역방향 트래버스가 없습니다.
has_next 함수를 작성하거나 원하는 경우 멋진 데코레이터가있는 메소드로 생성기에 적용 할 수도 있습니다.
-
==============================
2.암시:
암시:
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.
-
==============================
3.간단한 방법은 generator (또는 empty)가 고갈 된 경우에 사용되는 next ()에 선택적 매개 변수를 사용하는 것입니다. 예 :
간단한 방법은 generator (또는 empty)가 고갈 된 경우에 사용되는 next ()에 선택적 매개 변수를 사용하는 것입니다. 예 :
iterable = some_generator() _exhausted = object() if next(iterable, _exhausted) == _exhausted: print('generator is empty')
편집 : 문제를 해결 mehtunguh의 의견에 지적했다.
-
==============================
4.최선의 방법 인 IMHO는 특별한 테스트를 피하는 것입니다. 대부분의 경우 발전기를 사용하는 것이 테스트입니다.
최선의 방법 인 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)
충분하지 않으면 명시적인 테스트를 수행 할 수 있습니다. 이 시점에서 생성 된 마지막 값이 포함됩니다. 아무 것도 생성되지 않았다면 변수를 이미 정의하지 않았다면 정의되지 않을 것입니다. 당신은 물건의 가치를 확인할 수 있지만, 그것은 약간 신뢰할 수 없습니다. 대신 블록 내에 플래그를 설정하고 나중에 확인하십시오.
if not thing_generated: print "Avast, ye scurvy dog!"
-
==============================
5.다음 (생성자, 없음)이 없음
다음 (생성자, 없음)이 없음
아니면 아무 것도 바꾸지 말고 당신이 알고있는 어떤 값을 생성기에 넣지 마십시오.
편집 : 예,이 1 발전기에서 항목을 건너 뜁니다. 그러나 흔히 생성기가 유효성 검사 목적으로 만 비어 있는지 확인한 다음 실제로 사용하지 마십시오. 그렇지 않으면 나는 다음과 같은 것을한다.
def foo(self): if next(self.my_generator(), None) is None: raise Exception("Not initiated") for x in self.my_generator(): ...
즉, generator ()와 같이 함수에서 생성자를 가져 오는 경우에 작동합니다.
-
==============================
6.나는 두 번째 해결책, 특히 자신을 사용하지 않을 해결책을 제시하는 것을 싫어한다. 그러나 만약 당신이 절대적으로 이것을해야만하고 다른 해결책처럼 발전기를 소비하지 않는다면 :
나는 두 번째 해결책, 특히 자신을 사용하지 않을 해결책을 제시하는 것을 싫어한다. 그러나 만약 당신이 절대적으로 이것을해야만하고 다른 해결책처럼 발전기를 소비하지 않는다면 :
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)
이제는이 솔루션이 마음에 들지 않습니다. 왜냐하면 이것이 발전기의 사용 방법이 아니라고 생각하기 때문입니다.
-
==============================
7.분명한 접근 방식을 드려 죄송합니다.하지만 최선의 방법은 다음과 같습니다.
분명한 접근 방식을 드려 죄송합니다.하지만 최선의 방법은 다음과 같습니다.
for item in my_generator: print item
이제 발전기가 비어있는 것을 감지했습니다. 물론 발전기가 비어 있으면 항목이 표시되지 않습니다.
이 코드는 코드에 정확히 들어 맞지 않을 수도 있지만 생성자의 관용구는 다음과 같습니다. iterating, 접근 방식을 약간 바꿀 수도 있고 전혀 생성기를 사용하지 않을 수도 있습니다.
-
==============================
8.나는이 포스트가 5 살이라는 것을 알고 있지만, 이것을하는 관용적 인 방법을 찾고있는 동안 그것을 발견하고 내 솔루션이 게시 된 것을 보지 못했습니다. 그래서 후손을 위해 :
나는이 포스트가 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.
-
==============================
9.발전기가 비어 있는지보기 위해해야 할 일은 다음 결과를 얻으려고하는 것입니다. 물론 그 결과를 사용할 준비가되지 않았다면 나중에 저장하기 위해 저장해야합니다.
발전기가 비어 있는지보기 위해해야 할 일은 다음 결과를 얻으려고하는 것입니다. 물론 그 결과를 사용할 준비가되지 않았다면 나중에 저장하기 위해 저장해야합니다.
다음은 __nonzero__ 테스트를 추가하기 위해 기존 반복기에 추가 할 수있는 래퍼 클래스입니다. 따라서 생성자가 간단한 if로 비어 있는지 확인할 수 있습니다. 아마 데코레이터로 변할 수도 있습니다.
class GenWrapper: def __init__(self, iter): self.source = iter self.stored = False def __iter__(self): return self def __nonzero__(self): if self.stored: return True try: self.value = next(self.source) self.stored = True except StopIteration: return False return True def __next__(self): # use "next" (without underscores) for Python 2.x if self.stored: self.stored = False return self.value return next(self.source)
사용 방법은 다음과 같습니다.
with open(filename, 'r') as f: f = GenWrapper(f) if f: print 'Not empty' else: print 'Empty'
반복이 시작될 때뿐만 아니라 언제든지 공 없음을 확인할 수 있습니다.
-
==============================
10.
>>> gen = (i for i in []) >>> next(gen) Traceback (most recent call last): File "<pyshell#43>", line 1, in <module> next(gen) StopIteration
생성자의 끝에서 StopIteration이 발생합니다. 여러분의 경우 끝에 즉시 도달하기 때문에 예외가 발생합니다. 그러나 일반적으로 다음 가치의 존재를 확인해서는 안됩니다.
당신이 할 수있는 또 다른 일은 :
>>> gen = (i for i in []) >>> if not list(gen): print('empty generator')
-
==============================
11.필자는 필자가 함수를 전달하기 전에 다수의 생성자가 채워 졌는지 알 필요가 있었다.이 함수는 zip (...)과 같은 항목을 병합했다. 해결책은 유사하지만 수용된 답변에서 충분히 다릅니다.
필자는 필자가 함수를 전달하기 전에 다수의 생성자가 채워 졌는지 알 필요가 있었다.이 함수는 zip (...)과 같은 항목을 병합했다. 해결책은 유사하지만 수용된 답변에서 충분히 다릅니다.
정의:
def has_items(iterable): try: return True, itertools.chain([next(iterable)], iterable) except StopIteration: return False, []
용법:
def filter_empty(iterables): for iterable in iterables: itr_has_items, iterable = has_items(iterable) if itr_has_items: yield iterable def merge_iterables(iterables): populated_iterables = filter_empty(iterables) for items in zip(*populated_iterables): # Use items for each "slice"
내 문제는 iterables가 비어 있거나 정확히 같은 수의 항목을 가지고 있다는 속성이 있습니다.
-
==============================
12.발전기를 사용하기 전에 알아야 할 필요가 있다면 간단합니다. 발전기를 사용한 후까지 기다릴 수있는 간단한 방법이 있습니다.
발전기를 사용하기 전에 알아야 할 필요가 있다면 간단합니다. 발전기를 사용한 후까지 기다릴 수있는 간단한 방법이 있습니다.
was_empty = True for some_item in some_generator: was_empty = False do_something_with(some_item) if was_empty: handle_already_empty_generator_case()
-
==============================
13.다음은 무언가가 산출되었는지 확인하면서 반복자를 반환하는 데 사용하는 간단한 접근법입니다. 루프가 실행되는지 확인합니다.
다음은 무언가가 산출되었는지 확인하면서 반복자를 반환하는 데 사용하는 간단한 접근법입니다. 루프가 실행되는지 확인합니다.
n = 0 for key, value in iterator: n+=1 yield key, value if n == 0: print ("nothing found in iterator) break
-
==============================
14.다음은 생성자를 감싸는 단순한 데코레이터입니다. 따라서 비어있는 경우 None을 반환합니다. 이것은 코드가 루핑되기 전에 생성기가 어떤 것을 생성할지 여부를 알아야 할 때 유용합니다.
다음은 생성자를 감싸는 단순한 데코레이터입니다. 따라서 비어있는 경우 None을 반환합니다. 이것은 코드가 루핑되기 전에 생성기가 어떤 것을 생성할지 여부를 알아야 할 때 유용합니다.
def generator_or_none(func): """Wrap a generator function, returning None if it's empty. """ def inner(*args, **kwargs): # peek at the first item; return None if it doesn't exist try: next(func(*args, **kwargs)) except StopIteration: return None # return original generator otherwise first item will be missing return func(*args, **kwargs) return inner
용법:
import random @generator_or_none def random_length_generator(): for i in range(random.randint(0, 10)): yield i gen = random_length_generator() if gen is None: print('Generator is empty')
이것이 유용한 템플리트의 예는 jinja2입니다.
{% if content_generator %} <section> <h4>Section title</h4> {% for item in content_generator %} {{ item }} {% endfor % </section> {% endif %}
-
==============================
15.단순히 itertools.chain으로 생성기를 감싸고, iterable의 끝을 두 번째 iterable로 나타내는 무언가를 넣은 다음 간단히 확인하십시오.
단순히 itertools.chain으로 생성기를 감싸고, iterable의 끝을 두 번째 iterable로 나타내는 무언가를 넣은 다음 간단히 확인하십시오.
전의:
import itertools g = some_iterable eog = object() wrap_g = itertools.chain(g, [eog])
이제 남은 것은 iterable의 끝에 추가 된 값을 확인하는 것입니다.이 값을 읽으면 끝을 의미합니다.
for value in wrap_g: if value == eog: # DING DING! We just found the last element of the iterable pass # Do something
-
==============================
16.
islice를 사용하면 첫 번째 반복 만 검사하면 비어 있는지 확인할 수 있습니다.
-
==============================
17.any ()를 사용하는 것은 어떻습니까? 나는 발전기와 함께 그것을 사용하고 그것은 잘 작동합니다. 여기에 대해 약간 설명하는 사람이 있습니다.
any ()를 사용하는 것은 어떻습니까? 나는 발전기와 함께 그것을 사용하고 그것은 잘 작동합니다. 여기에 대해 약간 설명하는 사람이 있습니다.
-
==============================
18.cytoolz에서 peek 함수를 사용하십시오.
cytoolz에서 peek 함수를 사용하십시오.
from cytoolz import peek from typing import Tuple, Iterable def is_empty_iterator(g: Iterable) -> Tuple[Iterable, bool]: try: _, g = peek(g) return g, False except StopIteration: return g, True
이 함수가 리턴 한 반복자는 인수로 전달 된 원래의 반복자와 동일합니다.
-
==============================
19.마크 랜섬 (Mark Ransom)에 의해 요청 된 클래스는 반복기를 감싸서 앞으로 들여다보고 값을 다시 스트림으로 푸시하고 비어있는 것을 확인하는 데 사용할 수있는 클래스입니다. 간단하게 구현 한 간단한 아이디어로 과거에는 매우 편리하다고 생각했습니다.
마크 랜섬 (Mark Ransom)에 의해 요청 된 클래스는 반복기를 감싸서 앞으로 들여다보고 값을 다시 스트림으로 푸시하고 비어있는 것을 확인하는 데 사용할 수있는 클래스입니다. 간단하게 구현 한 간단한 아이디어로 과거에는 매우 편리하다고 생각했습니다.
class Pushable: def __init__(self, iter): self.source = iter self.stored = [] def __iter__(self): return self def __bool__(self): if self.stored: return True try: self.stored.append(next(self.source)) except StopIteration: return False return True def push(self, value): self.stored.append(value) def peek(self): if self.stored: return self.stored[-1] value = next(self.source) self.stored.append(value) return value def __next__(self): if self.stored: return self.stored.pop() return next(self.source)
-
==============================
20.나는 sum 함수를 사용하여 그것을 해결했다. glob.iglob (생성자를 반환)와 함께 사용한 예제는 아래를 참조하십시오.
나는 sum 함수를 사용하여 그것을 해결했다. glob.iglob (생성자를 반환)와 함께 사용한 예제는 아래를 참조하십시오.
def isEmpty(): files = glob.iglob(search) if sum(1 for _ in files): return True return False
* 이것은 아마 HUGE 제너레이터에서 작동하지 않을 것이지만 더 작은 목록에 대해서는 잘 수행되어야합니다
from https://stackoverflow.com/questions/661603/how-do-i-know-if-a-generator-is-empty-from-the-start by cc-by-sa and MIT license
'PYTHON' 카테고리의 다른 글
[PYTHON] 곱셈 (*)을 사용하여 하위 목록 생성 예기치 않은 동작 [복제] (0) | 2018.10.05 |
---|---|
[PYTHON] 왜 속성 참조가 파이썬 상속과 같은 역할을합니까? [복제] (0) | 2018.10.05 |
[PYTHON] Subplot에 여러 개의 Seaborn Jointplot을 그라인딩하는 방법 (0) | 2018.10.05 |
[PYTHON] 파이썬에서 문자열을 정수로 분리하는 방법은? (0) | 2018.10.04 |
[PYTHON] Python을 사용하여 Windows에서 폴더 권한 설정 (0) | 2018.10.04 |