[Python-checkins] CVS: python/nondist/peps pep-0255.txt,1.1,1.2
Tim Peters
tim_one@users.sourceforge.net
Wed, 13 Jun 2001 23:57:31 -0700
Update of /cvsroot/python/python/nondist/peps
In directory usw-pr-cvs1:/tmp/cvs-serv8864/python/nondist/peps
Modified Files:
pep-0255.txt
Log Message:
Substantial rewriting.
Index: pep-0255.txt
===================================================================
RCS file: /cvsroot/python/python/nondist/peps/pep-0255.txt,v
retrieving revision 1.1
retrieving revision 1.2
diff -C2 -r1.1 -r1.2
*** pep-0255.txt 2001/06/05 17:11:30 1.1
--- pep-0255.txt 2001/06/14 06:57:29 1.2
***************
*** 92,96 ****
very simple example:
! def fib(): a, b = 0, 1
while 1:
yield b
--- 92,97 ----
very simple example:
! def fib():
! a, b = 0, 1
while 1:
yield b
***************
*** 119,161 ****
Specification
! A new statement, the "yield" statement, is introduced:
! yield_stmt: "yield" [expression_list]
! This statement may only be used inside functions. A function which
! contains a yield statement is a so-called "generator function". A
! generator function may not contain return statements of the form:
! "return" expression_list
! It may, however, contain return statements of the form:
"return"
! When a generator function is called, an iterator[6] is returned.
! Each time the .next() method of this iterator is called, the code
! in the body of the generator function is executed until a yield
! statement or a return statement is encountered, or until the end
! of the body is reached.
!
! If a yield statement is encountered during this execution, the
! state of the function is frozen, and a value is returned to the
! object calling .next(). If an empty yield statement was
! encountered, None is returned; otherwise, the given expression(s)
! is (are) returned.
!
! If an empty return statement is encountered, nothing is returned;
! however, a StopIteration exception is raised, signalling that the
! iterator is exhausted.
! An example of how generators may be used is given below:
! # A binary tree class
class Tree:
def __init__(self, label, left=None, right=None):
self.label = label
self.left = left
self.right = right
! def __repr__(self, level=0, indent=" "):
s = level*indent + `self.label`
if self.left:
--- 120,183 ----
Specification
! A new statement is introduced:
! yield_stmt: "yield" expression_list
! "yield" is a new keyword, so a future statement[8] is needed to phase
! this in. [XXX spell this out]
! The yield statement may only be used inside functions. A function that
! contains a yield statement is called a generator function.
!
! 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. Instead a generator-iterator
! object is returned; this conforms to the iterator protocol[6], so in
! particular can be used in for-loops in a natural way. Note that when
! the intent is clear from context, the unqualified name "generator" may
! be used to refer either to a generator-function or a generator-
! iterator.
!
! Each time the .next() method of a generator-iterator is invoked, the
! code in the body of the generator-function is executed until a yield
! or return statement (see below) is encountered, or until the end of
! the body is reached.
!
! If a yield statement is encountered, the state of the function is
! frozen, and the value of expression_list is returned to .next()'s
! caller. By "frozen" we mean that all local state is retained,
! including the current bindings of local variables, the instruction
! pointer, and the internal evaluation stack: enough information is
! saved so that the next time .next() is invoked, the function can
! proceed exactly is if the yield statement were just another external
! call.
! A generator function can also contain return statements of the form:
"return"
! Note that an expression_list is not allowed on return statements
! in the body of a generator (although, of course, they may appear in
! the bodies of non-generator functions nested within the generator).
! When a return statement is encountered, nothing is returned, but a
! StopIteration exception is raised, signalling that the iterator is
! exhausted. The same is true if control flows off the end of the
! function. Note that return means "I'm done, and have nothing
! interesting to return", for both generator functions and non-generator
! functions.
!
! Example
!
! # A binary tree class.
class Tree:
+
def __init__(self, label, left=None, right=None):
self.label = label
self.left = left
self.right = right
!
! def __repr__(self, level=0, indent=" "):
s = level*indent + `self.label`
if self.left:
***************
*** 164,208 ****
s = s + "\n" + self.right.__repr__(level+1, indent)
return s
def __iter__(self):
return inorder(self)
!
! # A function that creates a tree from a list
def tree(list):
! if not len(list):
return []
! i = len(list)/2
return Tree(list[i], tree(list[:i]), tree(list[i+1:]))
!
! # A recursive generator that generates the tree leaves in in-order
def inorder(t):
if t:
! for x in inorder(t.left): yield x
yield t.label
! for x in inorder(t.right): yield x
!
! # Show it off: create a tree
t = tree("ABCDEFGHIJKLMNOPQRSTUVWXYZ")
! # Print the nodes of the tree in in-order
! for x in t: print x,
print
!
# A non-recursive generator.
def inorder(node):
! stack = []
! while node:
! while node.left:
! stack.append(node)
! node = node.left
! yield node.label
! while not node.right:
! try:
! node = stack.pop()
! except IndexError:
! return
! yield node.label
! node = node.right
!
! # Exercise the non-recursive generator
! for x in t: print x,
print
--- 186,236 ----
s = s + "\n" + self.right.__repr__(level+1, indent)
return s
+
def __iter__(self):
return inorder(self)
!
! # Create a Tree from a list.
def tree(list):
! n = len(list)
! if n == 0:
return []
! i = n / 2
return Tree(list[i], tree(list[:i]), tree(list[i+1:]))
!
! # A recursive generator that generates Tree leaves in in-order.
def inorder(t):
if t:
! for x in inorder(t.left):
! yield x
yield t.label
! for x in inorder(t.right):
! yield x
!
! # Show it off: create a tree.
t = tree("ABCDEFGHIJKLMNOPQRSTUVWXYZ")
! # Print the nodes of the tree in in-order.
! for x in t:
! print x,
print
!
# A non-recursive generator.
def inorder(node):
! stack = []
! while node:
! while node.left:
! stack.append(node)
! node = node.left
! yield node.label
! while not node.right:
! try:
! node = stack.pop()
! except IndexError:
! return
! yield node.label
! node = node.right
!
! # Exercise the non-recursive generator.
! for x in t:
! print x,
print
***************
*** 215,221 ****
Footnotes and References
! [1] PEP 234, http://python.sourceforge.net/peps/pep-0234.html
[2] http://www.stackless.com/
! [3] PEP 219, http://python.sourceforge.net/peps/pep-0219.html
[4] "Iteration Abstraction in Sather"
Murer , Omohundro, Stoutamire and Szyperski
--- 243,249 ----
Footnotes and References
! [1] PEP 234, http://python.sf.net/peps/pep-0234.html
[2] http://www.stackless.com/
! [3] PEP 219, http://python.sf.net/peps/pep-0219.html
[4] "Iteration Abstraction in Sather"
Murer , Omohundro, Stoutamire and Szyperski
***************
*** 223,228 ****
[5] http://www.cs.arizona.edu/icon/
[6] The concept of iterators is described in PEP 234
! http://python.sourceforge.net/peps/pep-0234.html
[7] http://python.ca/nas/python/generator.diff
--- 251,257 ----
[5] http://www.cs.arizona.edu/icon/
[6] The concept of iterators is described in PEP 234
! http://python.sf.net/peps/pep-0234.html
[7] http://python.ca/nas/python/generator.diff
+ [8] http://python.sf.net/peps/pep-0236.html