问题
The following code only prints "good". Why the generator function is not executed? I noticed with pdb that after executing 'handlers1' the script reaches the line with f1's definition but then does not get inside the function. Conversely, it's returned 'GeneratorExit: None'.
class foo:
def f0(self, s):
print s
def f1(self, s):
print "not " + s
yield 1
def run(self):
handlers={0 : self.f0, 1 : self.f1}
handlers[0]('good')
handlers[1]('good')
bar = foo()
bar.run()
Why this happens? Is it possible to call generator functions in a similar dynamic way?
回答1:
You need to call next
or the code in the generator won't run at all.
class foo:
def f0(self, s):
print s
def f1(self, s):
print "not " + s
yield 1
def run(self):
handlers={0 : self.f0, 1 : self.f1}
handlers[0]('good')
handlers[1]('good').next()
bar = foo()
bar.run()
That prints "good" then "not good".
回答2:
One does not invoke generator functions the same way one invokes normal functions. A generator function, when invoked, does not run but instead returns an iterator. This iterator, when passed to next()
or used in other iteration contexts, invokes the original function:
>>> def f1(s):
... print(s)
... yield
...
>>> it = f1("hello")
>>> next(it)
hello
>>>
To follow up on the discussion in another answer, here is a way to invoke either a regular function or a generator function:
>>> def f0(s):
... print s
...
>>> def f1(s):
... print s
... yield
...
>>> try: next(f0("hello"))
... except TypeError: pass
...
hello
>>> try: next(f1("hello"))
... except TypeError: pass
...
hello
>>>
回答3:
The generator function is called, but calling a generator function doesn't immediately do anything. Read the documentation, which explains:
When a generator function is called, the actual arguments are bound to function-local formal argument names in the usual way, but no code in the body of the function is executed.
回答4:
When you cann a generator function, it only returns an iterator. You should try to call the generator's next method to execute the body of generator function. Try this:
class foo:
def f0(self, s):
print s
def f1(self, s):
print "not " + s
yield 1
def run(self):
handlers={0 : self.f0, 1 : self.f1}
for _, func in handlers.iteritems():
res = func('good')
if hasattr(res, 'next'):
next(res)
bar = foo()
bar.run()
来源:https://stackoverflow.com/questions/18777544/dynamic-call-of-functions-and-generator-function-python