Визуальный Помогают, в целом, в то время как немного OT для этого вопроса, является большим приложением и действительно помогает с повседневной эксплуатацией Visual Studio. Их open-any-file и find-any-symbol окна являются особенно потрясающими.
>>> def foo():
... return 'foo'
...
>>> def bar():
... yield 'bar'
...
>>> import dis
>>> dis.dis(foo)
2 0 LOAD_CONST 1 ('foo')
3 RETURN_VALUE
>>> dis.dis(bar)
2 0 LOAD_CONST 1 ('bar')
3 YIELD_VALUE
4 POP_TOP
5 LOAD_CONST 0 (None)
8 RETURN_VALUE
>>>
Как видите, ключевое отличие состоит в том, что байт-код для bar
будет содержать по крайней мере один код операции YIELD_VALUE
. Я рекомендую использовать модуль dis
(перенаправляя его вывод в экземпляр StringIO и, конечно, проверяя его getvalue
), потому что это дает вам меру устойчивости к изменениям байт-кода - точные числовые значения кодов операций изменятся, но дизассемблированное символическое значение останется довольно стабильным; -).
На самом деле, мне интересно, насколько полезна такая гипотетическая is_generator_function ()
. Подумайте:
def foo():
return 'foo'
def bar():
yield 'bar'
def baz():
return bar()
def quux(b):
if b:
return foo()
else:
return bar()
Что должен is_generator_function ()
вернуть для baz
и quux
? baz ()
возвращает генератор, но не сам по себе, а quux ()
может возвращать генератор, а может и нет.