[Python-checkins] python/nondist/peps pep-0340.txt,1.15,1.16
gvanrossum@users.sourceforge.net
gvanrossum at users.sourceforge.net
Tue May 3 18:32:27 CEST 2005
Update of /cvsroot/python/python/nondist/peps
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv16785
Modified Files:
pep-0340.txt
Log Message:
Solidify loose ends.
Index: pep-0340.txt
===================================================================
RCS file: /cvsroot/python/python/nondist/peps/pep-0340.txt,v
retrieving revision 1.15
retrieving revision 1.16
diff -u -d -r1.15 -r1.16
--- pep-0340.txt 2 May 2005 23:35:52 -0000 1.15
+++ pep-0340.txt 3 May 2005 16:32:24 -0000 1.16
@@ -22,10 +22,6 @@
(Reliable Acquisition/Release Pairs), and PEP 325
(Resource-Release Support for Generators).
- This proposal is just a strawman; we've had a heated debate about
- this on python-dev recently [1], and I figured it would be time to
- write up a precise spec in PEP form.
-
Motivation and Summary
(Thanks to Shane Hathaway -- Hi Shane!)
@@ -70,7 +66,7 @@
Use Cases
- TBD. For now, see the Examples section near the end.
+ See the Examples section near the end.
Specification: the __next__() Method
@@ -159,14 +155,15 @@
This is also the case in the body of the block-statement proposed
below.
+ EXPR2 may contain commas; "continue 1, 2, 3" is equivalent to
+ "continue (1, 2, 3)".
+
Specification: the Anonymous Block Statement
A new statement is proposed with the syntax
block EXPR1 as VAR1:
BLOCK1
- else:
- BLOCK2
Here, 'block' and 'as' are new keywords; EXPR1 is an arbitrary
expression (but not an expression-list) and VAR1 is an arbitrary
@@ -268,14 +265,14 @@
the limitations of all finalization semantics) that the block will
be resumed eventually.
- I haven't decided yet whether the block-statement should also
- allow an optional else-clause, like the for-loop, but I'm leaning
- against it. I think it would be confusing, and emphasize the
+ Unlike the for-loop, the block-statement does not have an
+ else-clause. I think it would be confusing, and emphasize the
"loopiness" of the block-statement, while I want to emphasize its
*difference* from a for-loop. In addition, there are several
- possible semantics for an else-clause.
+ possible semantics for an else-clause, and only a very weak use
+ case.
-Specification: Generator Exception Handling
+Specification: Generator Exit Handling
Generators will implement the new __next__() method API, as well
as the old argument-less next() method which becomes an alias for
@@ -330,11 +327,10 @@
When __next__() is called with an argument that is not None, the
yield-expression that it resumes will return the value attribute
of the argument. If it resumes a yield-statement, the value is
- ignored (or should this be considered an error?). When the
- *initial* call to __next__() receives an argument that is not
- None, the generator's execution is started normally; the
- argument's value attribute is ignored (or should this be
- considered an error?). When __next__() is called without an
+ ignored (this is similar to ignoring the value returned by a
+ function call). When the *initial* call to __next__() receives an
+ argument that is not None, TypeError is raised; this is likely
+ caused by some logic error. When __next__() is called without an
argument or with None as argument, and a yield-expression is
resumed, the yield-expression returns None.
@@ -360,22 +356,20 @@
cases work differently; in Python, you cannot save the block for
later use, and you cannot test whether there is a block or not.
-Loose Ends
-
- These are things that need to be resolved before accepting the
- PEP.
+Alternatives Considered
- - Fill in the remaining TBD sections.
+ - Many alternatives have been proposed for 'block', including '@'
+ and no keyword at all. I haven't seen a proposal for another
+ keyword that I like better than 'block' yet, and not using a
+ keyword at all makes many folks (including me) uncomfortable.
- - Address Phillip Eby's proposal to have the block-statement use
+ - Phillip Eby has proposed to have the block-statement use
an entirely different API than the for-loop, to differentiate
- between the two (a generator would have to be wrapped in a
- decorator to make it support the block API).
-
- - Decide on the keyword ('block', 'with', '@', nothing, or
- something else?).
-
- - Whether a block-statement should allow an else-clause.
+ between the two. A generator would have to be wrapped in a
+ decorator to make it support the block API. IMO this adds more
+ complexity with very little benefit; and we can't relly deny
+ that the block-statement is conceptually a loop -- it supports
+ break and continue, after all.
Comparison to Thunks
@@ -418,7 +412,7 @@
and I'd be bummed if I couldn't write this as:
def findSomething(self, key, default=None):
- block synchronized(self.lock):
+ block locking(self.lock):
for item in self.elements:
if item.matches(key):
return item
@@ -427,7 +421,7 @@
This particular example can be rewritten using a break:
def findSomething(self, key, default=None):
- block synchronized(self.lock):
+ block locking(self.lock):
for item in self.elements:
if item.matches(key):
break
@@ -478,16 +472,17 @@
However, the use cases for multiple blocks seem elusive.
-Alternatives Considered
-
- TBD.
+ (Proposals have since been made to change the implementation of
+ thunks to remove most of these objections, but the resulting
+ semantics are fairly complex to explain and to implement, so IMO
+ that defeats the purpose of using thunks in the first place.)
Examples
1. A template for ensuring that a lock, acquired at the start of a
block, is released when the block is left:
- def synchronized(lock):
+ def locking(lock):
lock.acquire()
try:
yield
@@ -496,7 +491,7 @@
Used as follows:
- block synchronized(myLock):
+ block locking(myLock):
# Code here executes with myLock held. The lock is
# guaranteed to be released when the block is left (even
# if by an uncaught exception).
@@ -549,18 +544,40 @@
5. It is possible to nest blocks and combine templates:
- def synchronized_opening(lock, filename, mode="r"):
- block synchronized(lock):
+ def locking_opening(lock, filename, mode="r"):
+ block locking(lock):
block opening(filename) as f:
yield f
Used as follows:
- block synchronized_opening("/etc/passwd", myLock) as f:
+ block locking_opening("/etc/passwd", myLock) as f:
for line in f:
print line.rstrip()
- 6. Coroutine example TBD.
+ 6. It is possible to write a regular iterator with the
+ semantics of example 1:
+
+ class locking:
+ def __init__(self, lock):
+ self.lock = lock
+ self.state = 0
+ def __next__(self, arg=None):
+ # ignores arg
+ if self.state:
+ assert self.state == 1
+ self.lock.release()
+ self.state += 1
+ raise StopIteration
+ else:
+ self.lock.acquire()
+ self.state += 1
+ return None
+ def __exit__(self, type, value=None, traceback=None):
+ assert self.state in (0, 1, 2)
+ if self.state == 1:
+ self.lock.release()
+ raise type, value, traceback
Acknowledgements
More information about the Python-checkins
mailing list