Питонда функцияны «генераторлық функция» деп атағанға дейін тексеруге болады ма?

Менде екі функция бар:

 def foo(): return 'foo' def bar(): yield 'bar' 

Біріншісі қалыпты функция, екіншісі - генератор функциясы. Енді мен осылай жазғым келеді:

 def run(func): if is_generator_function(func): gen = func() gen.next() #... run the generator ... else: func() 

is_generator_function() іске асуы неге ұқсас? Түрлер пакетін қолдана отырып, gen генераторы екенін тексере аламын, бірақ func() қоңырау шалудан бұрын мұны істегім келеді.

Енді келесі жағдайды қарастырыңыз:

 def goo(): if False: yield else: return 

goo() қоңырауына генератор шақырады. Python талдаушы goo() функциясының кірістілік туралы мәлімдемесі бар екенін біледі және менің ойымша, бұл ақпарат алу оңай.

Рахмет!

46
09 дек. Карлос 09 желтоқсанда орнатқан . 2009-12-09 08:05 '09 сағат 8: 05- де 2009-12-09 08:05
@ 4 жауаптар
 >>> import inspect >>> >>> def foo(): ... return 'foo' ... >>> def bar(): ... yield 'bar' ... >>> print inspect.isgeneratorfunction(foo) False >>> print inspect.isgeneratorfunction(bar) True 
  • Python ішіндегі жаңа 2.6
53
20 июня '11 в 23:09 2011-06-20 23:09 жауап Corey Goldberg 20 маусым '23 at 23:09 2011-06-20 23:09

Шындығында, мұндай is_generator_function() қаншалықты пайдалы 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() 
border=0

is_generator_function() және quux үшін is_generator_function() қайсысы керек? baz() генераторды қайтарады, бірақ өзі емес, quux() генераторды қайтара алады немесе қайтара алмайды.

14
09 дек. Greg Hewgill берген 09 желтоқсан 2009-12-09 08:24 '09 сағат 8: 00-ден 2009-12-09 08:24
 >>> 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 >>> 

Көріп отырғаныңыздай, басты айырмашылығы, бар жолында байт кодында кем дегенде YIELD_VALUE операциялық коды YIELD_VALUE . Мен диск модулін пайдалануды ұсынамын (оның шығуын StringIO данасына қайта бағыттау және, әрине, оның getvalue тексеру), өйткені ол сізге кодты өзгерткен кезде сенімділіктің белгілі бір деңгейін қамтамасыз етеді - операция кодының нақты сандық мәндері өзгереді, бірақ сараланған символикалық мән қалыпты болып қалады ; -).

7
09 дек. жауапты Алекс Мартелли 09 желтоқсан. 2009-12-09 08:10 '09 at 8:10 am 2009-12-09 08:10

Мен безендірілген қайтару / берілетін мән функциясын орындайтын декораторды енгіздім. Оның негізгі ережелері:

 import types def output(notifier): def decorator(f): def wrapped(*args, **kwargs): r = f(*args, **kwargs) if type(r) is types.GeneratorType: for item in r: # do something yield item else: # do something return r return decorator 

Бұл декоратор функциясы шартсыз деп аталады, себебі бұл - жарамды қайтару мәні.


EDIT: Роберт Луженің түсініктемесіне сүйене отырып, мен бірдеңе жасадым:

 def middleman(f): def return_result(r): return r def yield_result(r): for i in r: yield i def decorator(*a, **kwa): if inspect.isgeneratorfunction(f): return yield_result(f(*a, **kwa)) else: return return_result(f(*a, **kwa)) return decorator 
1
17 июня '14 в 15:21 2014-06-17 15:21 жауап Damien 17 маусым '14 сағат 15:21 2014-06-17 15:21

Тегтер туралы басқа сұрақтар немесе сұрақ қойыңыз