2
#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.

4 Answers 4

2

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.

Sign up to request clarification or add additional context in comments.

Comments

2

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.

4 Comments

I thought that feature had gone in, but I could never find the source again after the first time I read it, and I don't have a Python 3 install to test with. Do you have a link to a PEP or something documenting the change?
PEP380. You can see the rule.@user2357112
Technically, you can use return in a generator in Python 2.x - you just can't return a value. It's equivalent to raising StopIteration.
I'm not sure this answers the question, though it's good information. You don't explain why Python doesn't allow you to return a value from a generator function.
0

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)

Comments

0

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.