Pythonでは、オブジェクトがジェネレータオブジェクトであるかどうかをどのように確認しますか?
これを試して-
>>> type(myobject, generator)
エラーを与える-
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'generator' is not defined
(オブジェクトにジェネレーターになるためのnext
メソッドがあるかどうかを確認できることは知っていますが、ジェネレーターだけでなく、オブジェクトのタイプを判別できる何らかの方法が必要です。)
GeneratorTypeは次のタイプから使用できます。
>>> import types
>>> types.GeneratorType
<class 'generator'>
>>> gen = (i for i in range(10))
>>> isinstance(gen, types.GeneratorType)
True
ジェネレーター関数ですか?つかいます - inspect.isgeneratorfunction
。
編集:
ジェネレータオブジェクトが必要な場合は、JABのコメントで指摘されているように、 inspect.isgenerator を使用できます。
generator functionsとgenerators(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]
inspect.isgenerator
関数は、純粋なジェネレーター(つまり、クラス "generator"のオブジェクト)を確認したい場合に適しています。ただし、たとえばFalse
イテラブルをチェックすると、izip
が返されます。一般化されたジェネレータをチェックする別の方法は、この関数を使用することです:
def isgenerator(iterable):
return hasattr(iterable,'__iter__') and not hasattr(iterable,'__len__')
>>> import inspect
>>>
>>> def foo():
... yield 'foo'
...
>>> print inspect.isgeneratorfunction(foo)
True
オブジェクトにジェネレーターになるための次のメソッドがあるかどうかを確認できることは知っていますが、ジェネレーターだけでなく、オブジェクトのタイプを判別できる何らかの方法が必要です。
これをしないでください。それは単純に非常に悪い考えです。
代わりに、これを行います:
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ループの本体にもTypeError
sがある場合、(1)エラーの範囲を制限する関数を定義するか、(2)ネストされたtryブロックを使用します。
または、(3)浮かんでいるこれらのTypeError
sをすべて区別するためのこのようなもの。
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)アプリケーションの他の部分を修正して、ジェネレーターを適切に提供します。これは、多くの場合これよりも簡単です。
トルネードウェブサーバーなどを使用している場合、サーバーメソッドは実際にはジェネレーターであり、メソッドではないことがわかります。メソッド内で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]
スレッドの代替または類似物としてジェネレータを使用したい場合、おそらくあなたが望むものです。