[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