web-dev-qa-db-ja.com

オブジェクトがPythonのジェネレータオブジェクトであるかどうかを確認するにはどうすればよいですか?

Pythonでは、オブジェクトがジェネレータオブジェクトであるかどうかをどのように確認しますか?

これを試して-

>>> type(myobject, generator)

エラーを与える-

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

(オブジェクトにジェネレーターになるためのnextメソッドがあるかどうかを確認できることは知っていますが、ジェネレーターだけでなく、オブジェクトのタイプを判別できる何らかの方法が必要です。)

127
Pushpak Dagade

GeneratorTypeは次のタイプから使用できます。

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

ジェネレーター関数ですか?つかいます - inspect.isgeneratorfunction

編集:

ジェネレータオブジェクトが必要な場合は、JABのコメントで指摘されているように、 inspect.isgenerator を使用できます。

33
mouad

generator functionsgenerators(generator functionの結果)を区別することが重要だと思います:

>>> 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]

In python関数を呼び出す前に関数が「ジェネレータ関数」であるかどうかを確認する方法はありますか?

16
Robert Lujo

inspect.isgenerator関数は、純粋なジェネレーター(つまり、クラス "generator"のオブジェクト)を確認したい場合に適しています。ただし、たとえばFalseイテラブルをチェックすると、izipが返されます。一般化されたジェネレータをチェックする別の方法は、この関数を使用することです:

def isgenerator(iterable):
    return hasattr(iterable,'__iter__') and not hasattr(iterable,'__len__')
11
Luca Sbardella
>>> import inspect
>>> 
>>> def foo():
...   yield 'foo'
... 
>>> print inspect.isgeneratorfunction(foo)
True
2
Corey Goldberg

オブジェクトにジェネレーターになるための次のメソッドがあるかどうかを確認できることは知っていますが、ジェネレーターだけでなく、オブジェクトのタイプを判別できる何らかの方法が必要です。

これをしないでください。それは単純に非常に悪い考えです。

代わりに、これを行います:

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)浮かんでいるこれらのTypeErrorsをすべて区別するためのこのようなもの。

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)アプリケーションの他の部分を修正して、ジェネレーターを適切に提供します。これは、多くの場合これよりも簡単です。

2
S.Lott

トルネードウェブサーバーなどを使用している場合、サーバーメソッドは実際にはジェネレーターであり、メソッドではないことがわかります。メソッド内でyieldが機能していないため、チェーンされたジェネレーターオブジェクトのプールの管理を開始する必要があるため、他のメソッドを呼び出すことが難しくなります。連鎖ジェネレーターのプールを管理する簡単な方法は、次のようなヘルプ機能を作成することです

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
user6830669