]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
Change the semantics of "return" in generators, as discussed on the
authorTim Peters <tim.peters@gmail.com>
Sat, 23 Jun 2001 06:19:16 +0000 (06:19 +0000)
committerTim Peters <tim.peters@gmail.com>
Sat, 23 Jun 2001 06:19:16 +0000 (06:19 +0000)
Iterators list and Python-Dev; e.g., these all pass now:

def g1():
    try:
        return
    except:
        yield 1
assert list(g1()) == []

def g2():
    try:
        return
    finally:
        yield 1
assert list(g2()) == [1]

def g3():
    for i in range(3):
        yield None
    yield None
assert list(g3()) == [None] * 4

compile.c:  compile_funcdef and com_return_stmt:  Just van Rossum's patch
to compile the same code for "return" regardless of function type (this
goes back to the previous scheme of returning Py_None).

ceval.c:  gen_iternext:  take a return (but not a yield) of Py_None as
meaning the generator is exhausted.

Python/ceval.c
Python/compile.c

index d334775fbe36900d684efa81a032010dd8ab0701..6a1ba50020e36b9db54b95ea1c48cb723ef60cd6 100644 (file)
@@ -166,6 +166,13 @@ gen_iternext(genobject *gen)
        Py_XDECREF(f->f_back);
        f->f_back = NULL;
 
+       /* If the generator just returned (as opposed to yielding), signal
+        * that the generator is exhausted. */
+       if (result == Py_None && f->f_stacktop == NULL) {
+               Py_DECREF(result);
+               result = NULL;
+       }
+
        return result;
 }
 
index 843cf098e842838a7ee2e27669dc1e19d2082364..2ce7487179de1a8801ab684ba84e173fa64f6029 100644 (file)
@@ -2639,20 +2639,14 @@ com_return_stmt(struct compiling *c, node *n)
                        com_error(c, PyExc_SyntaxError,
                                  "'return' with argument inside generator");
                }
-               com_addoparg(c, LOAD_CONST,
-                               com_addconst(c, PyExc_StopIteration));
-               com_push(c, 1);
-               com_addoparg(c, RAISE_VARARGS, 1);
        }
-       else {
-               if (NCH(n) < 2) {
-                       com_addoparg(c, LOAD_CONST, com_addconst(c, Py_None));
-                       com_push(c, 1);
-               }
-               else
-                       com_node(c, CHILD(n, 1));
-               com_addbyte(c, RETURN_VALUE);
+       if (NCH(n) < 2) {
+               com_addoparg(c, LOAD_CONST, com_addconst(c, Py_None));
+               com_push(c, 1);
        }
+       else
+               com_node(c, CHILD(n, 1));
+       com_addbyte(c, RETURN_VALUE);
        com_pop(c, 1);
 }
 
@@ -3711,19 +3705,10 @@ compile_funcdef(struct compiling *c, node *n)
        c->c_infunction = 1;
        com_node(c, CHILD(n, 4));
        c->c_infunction = 0;
-       if (c->c_flags & CO_GENERATOR) {
-               com_addoparg(c, LOAD_CONST,
-                               com_addconst(c, PyExc_StopIteration));
-               com_push(c, 1);
-               com_addoparg(c, RAISE_VARARGS, 1);
-               com_pop(c, 1);
-       }
-       else {
-               com_addoparg(c, LOAD_CONST, com_addconst(c, Py_None));
-               com_push(c, 1);
-               com_addbyte(c, RETURN_VALUE);
-               com_pop(c, 1);
-       }
+       com_addoparg(c, LOAD_CONST, com_addconst(c, Py_None));
+       com_push(c, 1);
+       com_addbyte(c, RETURN_VALUE);
+       com_pop(c, 1);
 }
 
 static void