파이썬에서 객체가 생성기 객체인지 확인하는 방법은 무엇입니까?


157

파이썬에서 객체가 생성기 객체인지 어떻게 확인합니까?

이것을 시도-

>>> type(myobject, generator)

오류를 준다-

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'generator' is not defined

(객체 next에 생성자가 될 수 있는 방법 이 있는지 확인할 수는 있지만 생성기뿐만 아니라 모든 객체의 유형을 결정할 수있는 방법을 원합니다.)


4
어떤 실제 문제를 해결하려고합니까? 더 많은 맥락을 게시하면 더 똑똑한 방법이있을 수 있습니다. 왜 발전기인지 알아야합니까?
니트

7
from types import GeneratorType;type(myobject, GeneratorType)클래스 'generator'의 객체에 대한 올바른 결과를 제공합니다. 그러나 데니스가 암시 하듯이, 반드시 올바른 길로가는 것은 아닙니다.
JAB

7
를 확인하는 경우 __next__실제로 생성기뿐만 아니라 반복자를 허용합니다. 원하는 것 같습니다.

2
종종 생성자가 아닌지 아는 실제 지점은 동일한 콜렉션에 대해 여러 번 반복하기를 원하므로 피할 수 있어야합니다.
Ian

2
유스 케이스에 대해 궁금해하는 사람들에게는 반복자가 소비되는지 알아야 할 때 유용합니다 (예 : 함수가 반복자를 허용하지만 두 번 이상 반복해야하는 경우 반복하기 전에 구체화해야 함)
wbadart

답변:


227

다음 유형에서 GeneratorType을 사용할 수 있습니다.

>>> import types
>>> types.GeneratorType
<class 'generator'>
>>> gen = (i for i in range(10))
>>> isinstance(gen, types.GeneratorType)
True

5
불행히도 생성기 클래스 (예 : 맵 또는 필터 객체)에서는 작동하지 않습니다.
Ricardo Cruz

아마 isinstance(gen, (types.GeneratorType, map, filter))또한 감지하는 데 유용 map하고 filter. 여기에는 여전히 다른 반복자 및 반복자가 포함되지 않습니다.
jlh

38

발전기 기능을 의미합니까? 사용하십시오 inspect.isgeneratorfunction.

편집하다 :

생성기 객체를 원한다면 JAB가 주석에서 지적한 바와 같이 inspect.isgenerator 를 사용할 수 있습니다 .


1
제너레이터 기능은 제너레이터 객체가 아닙니다. @utdemir의 답변 참조
Piotr Findeisen

5
@Piotr : 어떤 경우에을 사용 inspect.isgenerator합니다.
JAB

@JAB, @Piotr : JAB 덕분에 OP가 의미 할 수있는 모든 가능성을 해결하기 위해 반영 :)
mouad

1
참고 : 당신은이 테스트를 필요로하는 경우, 당신은 사용하여 작은 오버 헤드를 피할 수 @utdemir 솔루션을 하기 때문에 inspect.isgenerator단지 속기가하는 것입니다 isinstance(object, types.GeneratorType).
bufh

생성기 객체와 생성기 함수의 구별에 대해서는 @RobertLujo 답변을 참조하십시오. stackoverflow.com/a/32380774/3595112
industryworker3595112

24

생성기 함수생성기 (생성기 함수의 결과)를 구별하는 것이 중요하다고 생각합니다 .

>>> def generator_function():
...     yield 1
...     yield 2
...
>>> import inspect
>>> inspect.isgeneratorfunction(generator_function)
True

generator_function을 호출하면 정상적인 결과를 얻지 못하고 함수 자체에서 코드를 실행하지 않으며 결과는 generator 라는 특수 객체가됩니다 .

>>> generator = generator_function()
>>> generator
<generator object generator_function at 0x10b3f2b90>

따라서 생성기 기능이 아니라 생성기입니다.

>>> inspect.isgeneratorfunction(generator)
False

>>> import types
>>> isinstance(generator, types.GeneratorType)
True

발전기 기능은 발전기가 아닙니다.

>>> isinstance(generator_function, types.GeneratorType)
False

참고로 함수 본문의 실제 호출은 생성기를 소비하여 발생합니다. 예 :

>>> list(generator)
[1, 2]

참조 파이썬에서 함수를 호출하기 전에 "발전기 기능"이 있는지 확인하는 방법은 무엇입니까?


11

inspect.isgenerator당신이 순수 발전기 (즉 클래스 "발전기"의 객체)를 확인하려면 기능은 괜찮습니다. 그러나 False예를 들어 izipiterable 을 확인 하면 반환 됩니다 . 일반화 된 발전기를 확인하는 다른 방법은이 기능을 사용하는 것입니다.

def isgenerator(iterable):
    return hasattr(iterable,'__iter__') and not hasattr(iterable,'__len__')

1
흠. 에 대해 true를 반환합니다 x=iter([1,2]). 객체가 생성자 가 아닌 반복자 인지 실제로 테스트하고있는 것 같습니다 . 그러나 "iterator"는 "generalized generator"의 의미입니다.
Josh O'Brien 1

3

타이핑 모듈 에서 Iterator 또는보다 구체적으로 Generator를 사용할 수 있습니다 .

from typing import Generator, Iterator
g = (i for i in range(1_000_000))
print(type(g))
print(isinstance(g, Generator))
print(isinstance(g, Iterator))

결과:

<class 'generator'>
True
True

1
작동하는 솔루션의 경우 +1 이 존재는 대한 문서 말했다 typing.TypeVar클래스의 사용을 억제하는 것 isinstance와 함께 typing", 런타임시 : 모듈을 isinstance(x, T)올릴 것이다 TypeError일반적으로. isinstance()그리고 issubclass()유형 사용할 수 없습니다."
Jasha

2
>>> import inspect
>>> 
>>> def foo():
...   yield 'foo'
... 
>>> print inspect.isgeneratorfunction(foo)
True

함수 인 경우에만 작동합니다. 'foo'가 생성기 객체 인 경우 'False'가 표시됩니다. 내 질문을 참조하십시오. 제너레이터 객체를 확인하고 싶습니다.
Pushpak Dagade 2016 년

2

객체에 생성기가 될 다음 방법이 있는지 확인할 수 있지만 생성기뿐만 아니라 모든 객체의 유형을 결정할 수있는 방법을 원합니다.

이러지 마 그것은 단지 매우, 매우 나쁜 생각입니다.

대신 다음을 수행하십시오.

try:
    # Attempt to see if you have an iterable object.
    for i in some_thing_which_may_be_a_generator:
        # The real work on `i`
except TypeError:
     # some_thing_which_may_be_a_generator isn't actually a generator
     # do something else

드문 경우지만 for 루프 의 본문에 TypeErrors가 있으면 (1) 오류 범위를 제한하는 함수를 정의하거나 (2) 중첩 된 try 블록을 사용하십시오.

또는 (3) TypeError떠 다니는 모든 것을 구별하기 위해 이와 같은 것 .

try:
    # Attempt to see if you have an iterable object.
    # In the case of a generator or iterator iter simply 
    # returns the value it was passed.
    iterator = iter(some_thing_which_may_be_a_generator)
except TypeError:
     # some_thing_which_may_be_a_generator isn't actually a generator
     # do something else
else:
    for i in iterator:
         # the real work on `i`

또는 (4) 응용 프로그램의 다른 부분을 수정하여 생성기를 적절하게 제공하십시오. 종종이 모든 것보다 간단합니다.


1
솔루션은 for 루프의 본문에서 발생하는 TypeError를 잡습니다. 이 바람직하지 않은 동작을 방지하는 편집을 제안했습니다.
모래 언덕

내가 실수하지 않으면 이것이 더 파이썬적인 방법입니다.
JAB

그러나 항목 목록을 반복하고 반복자보다 많은 항목이 반복자가 아닌 경우 확실히 더 오래 걸릴 수 있습니까?
Jakob Bowyer 2018 년

1
@Jakob Bowyer : 예외는 if문장 보다 빠릅니다 . 과. 그런 종류의 미세 최적화는 시간 낭비입니다. 반복자 만 생성하고 반복자가 아닌 반복자를 생성하는 알고리즘을 수정하여 반복자 만 생성하고이 모든 고통을 해결하십시오.
S.Lott

10
이것은 실수로 생성자를 반복자로 가정합니다.
balki

1

토네이도 웹 서버 또는 이와 유사한 것을 사용하는 경우 서버 메소드가 실제로 생성자가 아니라 메소드라는 것을 알 수 있습니다. 수율이 메소드 내부에서 작동하지 않기 때문에 다른 메소드를 호출하기가 어렵 기 때문에 체인 생성기 오브젝트 풀 관리를 시작해야합니다. 체인 생성기 풀을 관리하는 간단한 방법은 다음과 같은 도움말 기능을 만드는 것입니다.

def chainPool(*arg):
    for f in arg:
      if(hasattr(f,"__iter__")):
          for e in f:
             yield e
      else:
         yield f

이제 다음과 같은 체인 생성기를 작성하십시오.

[x for x in chainPool(chainPool(1,2),3,4,chainPool(5,chainPool(6)))]

출력물 생성

[1, 2, 3, 4, 5, 6]

생성기를 스레드 대안 또는 이와 유사한 것으로 사용하려는 경우 아마도 당신이 원하는 것입니다.


1

(이것은 오래된 게시물이라는 것을 알고 있습니다.) 모듈을 가져올 필요가 없으며 프로그램 시작시 비교를 위해 객체를 선언 할 수 있습니다.

gentyp= type(1 for i in "")                                                                                          
       ...
type(myobject) == gentyp
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.