복붙노트

[PYTHON] 처음부터 발전기가 비어 있는지 어떻게 알 수 있습니까?

PYTHON

처음부터 발전기가 비어 있는지 어떻게 알 수 있습니까?

생성기에 peek, hasNext, isEmpty 등과 같은 항목이없는 경우 간단한 방법으로 테스트 할 수 있습니까?

해결법

  1. ==============================

    1.귀하의 질문에 대한 간단한 대답 : 아니오, 간단한 방법이 없습니다. 해결 방법이 많이 있습니다.

    귀하의 질문에 대한 간단한 대답 : 아니오, 간단한 방법이 없습니다. 해결 방법이 많이 있습니다.

    생성기가 무엇인지 간단하기 때문에 간단한 방법이 있어서는 안됩니다. 시퀀스를 메모리에 보관하지 않고 값의 시퀀스를 출력하는 방법입니다. 따라서 역방향 트래버스가 없습니다.

    has_next 함수를 작성하거나 원하는 경우 멋진 데코레이터가있는 메소드로 생성기에 적용 할 수도 있습니다.

  2. ==============================

    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. ==============================

    3.간단한 방법은 generator (또는 empty)가 고갈 된 경우에 사용되는 next ()에 선택적 매개 변수를 사용하는 것입니다. 예 :

    간단한 방법은 generator (또는 empty)가 고갈 된 경우에 사용되는 next ()에 선택적 매개 변수를 사용하는 것입니다. 예 :

    iterable = some_generator()
    
    _exhausted = object()
    
    if next(iterable, _exhausted) == _exhausted:
        print('generator is empty')
    

    편집 : 문제를 해결 mehtunguh의 의견에 지적했다.

  4. ==============================

    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. ==============================

    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. ==============================

    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. ==============================

    7.분명한 접근 방식을 드려 죄송합니다.하지만 최선의 방법은 다음과 같습니다.

    분명한 접근 방식을 드려 죄송합니다.하지만 최선의 방법은 다음과 같습니다.

    for item in my_generator:
         print item
    

    이제 발전기가 비어있는 것을 감지했습니다. 물론 발전기가 비어 있으면 항목이 표시되지 않습니다.

    이 코드는 코드에 정확히 들어 맞지 않을 수도 있지만 생성자의 관용구는 다음과 같습니다. iterating, 접근 방식을 약간 바꿀 수도 있고 전혀 생성기를 사용하지 않을 수도 있습니다.

  8. ==============================

    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. ==============================

    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. ==============================

    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. ==============================

    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. ==============================

    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. ==============================

    13.다음은 무언가가 산출되었는지 확인하면서 반복자를 반환하는 데 사용하는 간단한 접근법입니다. 루프가 실행되는지 확인합니다.

    다음은 무언가가 산출되었는지 확인하면서 반복자를 반환하는 데 사용하는 간단한 접근법입니다. 루프가 실행되는지 확인합니다.

            n = 0
            for key, value in iterator:
                n+=1
                yield key, value
            if n == 0:
                print ("nothing found in iterator)
                break
    
  14. ==============================

    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. ==============================

    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. ==============================

    16.

    islice를 사용하면 첫 번째 반복 만 검사하면 비어 있는지 확인할 수 있습니다.

  17. ==============================

    17.any ()를 사용하는 것은 어떻습니까? 나는 발전기와 함께 그것을 사용하고 그것은 잘 작동합니다. 여기에 대해 약간 설명하는 사람이 있습니다.

    any ()를 사용하는 것은 어떻습니까? 나는 발전기와 함께 그것을 사용하고 그것은 잘 작동합니다. 여기에 대해 약간 설명하는 사람이 있습니다.

  18. ==============================

    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. ==============================

    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. ==============================

    20.나는 sum 함수를 사용하여 그것을 해결했다. glob.iglob (생성자를 반환)와 함께 사용한 예제는 아래를 참조하십시오.

    나는 sum 함수를 사용하여 그것을 해결했다. glob.iglob (생성자를 반환)와 함께 사용한 예제는 아래를 참조하십시오.

    def isEmpty():
        files = glob.iglob(search)
        if sum(1 for _ in files):
            return True
        return False
    

    * 이것은 아마 HUGE 제너레이터에서 작동하지 않을 것이지만 더 작은 목록에 대해서는 잘 수행되어야합니다

  21. 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