Reputation: 2948
#def func(param):
# if param < 0:
# return "test"
# i = 0
# while i < param:
# yield i
# i += 1
def func(param):
if param < 0:
return "test"
def gen(n):
i = 0
while i < param:
yield i
i += 1
return gen(param)
print(func(-1))
print(func(3))
g = func(3)
for i in range(0, 3):
print(next(g))
Is there a reason that the Python interpreter can not convert the commented code to the actual code implicitly? This seems like this should be allowed, but I am wondering what repercussions there are that made them choose to disallow this.
Upvotes: 2
Views: 242
Reputation: 169623
The reason is simply, if the def
contains a yield
statement, it creates a generator:
http://www.python.org/dev/peps/pep-0255/
The yield statement may only be used inside functions. A function that contains a yield statement is called a generator function. A generator function is an ordinary function object in all respects, but has the new CO_GENERATOR flag set in the code object's co_flags member.
That is how the interpreter distinguishes between a regular function, and a generator function. It's simple to implement, easy to reason about ("if it contains a yield
, it's a generator")
The "conditional generator" behaviour you describe would be much more complex to implement, and in some cases not desirable (maybe the conditional should happen inside the first iteration of the generator, or maybe it should run as soon as you call func(...)
)
Your other code either returns a generator, or a string. If that's the interface you want, it seems like a perfectly good solution (but it's hard to make practical suggestions without a real example)
Upvotes: 0
Reputation: 8610
In python2.x, you can not return something in a generator:
>>> def func():
... return 3
... yield 3
...
File "<stdin>", line 3
SyntaxError: 'return' with argument inside generator
>>>
In python3.x, use return
in a generator means raise a StopIteration(<something>)
:
>>> def func():
... return 3
... yield 3
...
>>> func().__next__()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration: 3
>>>
I can not think about any reason for the interpreter to decide which part is a generator. It is hard and I think it is the responsibilities of programmers. And I even doubt whether return a value in a generator is a good implementation.
Upvotes: 2
Reputation: 81
generators are declared like functions but are different, you cant use a return statement in generator what you should do is:
def func(param):
if param < 0:
yield "test"
raise StopIteration()
i = 0
while i < param:
yield i
i += 1
an even better implmention would be:
def func(param):
if param < 0:
raise ValueError("param must be a positive number")
i = 0
while i < param:
yield i
i += 1
Upvotes: 0
Reputation: 176880
When you call a generator function, you know what type of object it will return -- a generator. If we allowed generator functions to return
, then you'd have to check the type of the return value before you could start iterating over the generator, so you'd no longer have a generator function -- just a function that might return a generator.
Upvotes: 2