python/nondist/peps pep-0340.txt,1.15,1.16
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
participants (1)
-
gvanrossumļ¼ users.sourceforge.net