From 3442cf7d153e8cdca5f97a75c8e1854ad6304674 Mon Sep 17 00:00:00 2001 From: Nick Coghlan Date: Sun, 16 Oct 2011 13:10:10 +1000 Subject: [PATCH] Kill PEP 403 in light of python-ideas discussion. Resurrect PEP 3150 with first cut updates based on PEP 403 feedback --- pep-0403.txt | 45 ++---- pep-3150.txt | 450 ++++++++++++++++++++++++++++++++++++--------------- 2 files changed, 340 insertions(+), 155 deletions(-) diff --git a/pep-0403.txt b/pep-0403.txt index 4f78221e9..347378c2e 100644 --- a/pep-0403.txt +++ b/pep-0403.txt @@ -3,7 +3,7 @@ Title: Prefix syntax for post function definition operations Version: $Revision$ Last-Modified: $Date$ Author: Nick Coghlan -Status: Deferred +Status: Withdrawn Type: Standards Track Content-Type: text/x-rst Created: 2011-10-13 @@ -32,20 +32,14 @@ Namespaces) so some elements of the rationale will be familiar to readers of that PEP. That PEP has now been withdrawn in favour of this one. -PEP Deferral -============ +PEP Withdrawal +============== -Like PEP 3150, this PEP currently exists in a deferred state. Unlike PEP 3150, -this isn't because I suspect it might be a terrible idea or see nasty problems -lurking in the implementation (aside from one potential parsing issue). - -Instead, it's because I think fleshing out the concept, exploring syntax -variants, creating a reference implementation and generally championing -the idea is going to require more time than I can give it in the 3.3 time -frame. - -So, it's deferred. If anyone wants to step forward to drive the PEP for 3.3, -let me know and I can add you as co-author and move it to Draft status. +The python-ideas thread discussing this PEP [1]_ persuaded me that it was +essentially am unnecessarily cryptic, wholly inferior version of PEP 3150's +statement local namespaces. The discussion also resolved some of my concerns +with PEP 3150, so I am withdrawing this more limited version of the idea in +favour of resurrecting the original concept. Basic Examples @@ -259,7 +253,7 @@ Calculating attributes without polluting the local namespace (from os.py):: del _createenviron # Becomes: - :environ = @() + postdef environ = def() def _createenviron(): ... # 27 line function @@ -269,14 +263,14 @@ Loop early binding:: funcs = [(lambda x, i=i: x + i) for i in range(10)] # Becomes: - :funcs = [@(i) for i in range(10)] + postdef funcs = [def(i) for i in range(10)] def make_incrementor(i): return lambda x: x + i # Or even: - :funcs = [@(i) for i in range(10)] + postdef funcs = [def(i) for i in range(10)] def make_incrementor(i): - :return @ + postdef return def def incrementor(x): return x + i @@ -287,15 +281,6 @@ Reference Implementation None as yet. -TO DO -===== - -Sort out links and references to everything :) - -Start of python-ideas thread: -http://mail.python.org/pipermail/python-ideas/2011-October/012276.html - - Acknowledgements ================ @@ -303,11 +288,15 @@ Huge thanks to Gary Bernhardt for being blunt in pointing out that I had no idea what I was talking about in criticising Ruby's blocks, kicking off a rather enlightening process of investigation. +Even though this PEP has been withdrawn, the process of writing and arguing +in its favour has been quite influential on the future direction of PEP 3150. + References ========== -TBD +[1] Start of python-ideas thread: + http://mail.python.org/pipermail/python-ideas/2011-October/012276.html Copyright diff --git a/pep-3150.txt b/pep-3150.txt index 911707647..b1e63e425 100644 --- a/pep-3150.txt +++ b/pep-3150.txt @@ -3,11 +3,11 @@ Title: Statement local namespaces (aka "given" clause) Version: $Revision$ Last-Modified: $Date$ Author: Nick Coghlan -Status: Withdrawn +Status: Deferred Type: Standards Track Content-Type: text/x-rst Created: 2010-07-09 -Python-Version: 3.3 +Python-Version: 3.4 Post-History: 2010-07-14, 2011-04-21, 2011-06-13 Resolution: TBD @@ -21,46 +21,70 @@ clause will create a statement local namespace for additional names that are accessible in the associated statement, but do not become part of the containing namespace. -The primary motivation is to elevate ordinary assignment statements to be -on par with ``class`` and ``def`` statements where the name of the item to -be defined is presented to the reader in advance of the details of how the -value of that item is calculated. +The primary motivation is to enable a more declarative style of programming, +where the operation to be performed is presented to the reader first, and the +details of the necessary subcalculations are presented in the following +indented suite. As a key example, this would elevate ordinary assignment +statements to be on par with ``class`` and ``def`` statements where the name +of the item to be defined is presented to the reader in advance of the +details of how the value of that item is calculated. It also allows named +functions to be used in a "multi-line lambda" fashion, where the name is used +solely as a placeholder in the current expression and then defined in the +following suite. A secondary motivation is to simplify interim calculations in module and class level code without polluting the resulting namespaces. -There are additional emergent properties of the proposed solution which may -be of interest to some users. Most notably, it is proposed that this clause -use a new kind of scope that performs early binding of variables, potentially -replacing other techniques that achieve the same effect (such as the "default -argument hack"). +The intent is that the relationship between a given clause and a separate +function definition that performs the specified operation will be similar to +the existing relationship between an explicit while loop and a generator that +produces the same sequence of operations as that while loop. The specific proposal in this PEP has been informed by various explorations -of this and related concepts over the years (e.g. [1], [2], [3], [6]), and is -inspired to some degree by the ``where`` and ``let`` clauses in Haskell. It -avoids some problems that have been identified in past proposals, but has not -yet itself been subject to the test of implementation. +of this and related concepts over the years (e.g. [1]_, [2]_, [3]_, [6]_, +[8]_), and is inspired to some degree by the ``where`` and ``let`` clauses in +Haskell. It avoids some problems that have been identified in past proposals, +but has not yet itself been subject to the test of implementation. PEP Deferral ============ Despite the lifting of the language moratorium (PEP 3003) for Python 3.3, -this PEP currently remains in a Deferred state. That means the PEP has to -pass at least *two* hurdles to become part of 3.3. +this PEP currently remains in a Deferred state. This idea, if implemented, +will potentially have a deep and pervasive effect on the way people write +Python code. -Firstly, I personally have to be sufficiently convinced of the PEP's value and -feasibility to return it to Draft status. While I do see merit in the concept -of statement local namespaces (otherwise I wouldn't have spent so much time -pondering the idea over the years), I also have grave doubts as to the wisdom -of actually adding it to the language (see "Key Concern" below). +When this PEP was first put forward, even I, as the PEP author, was not +convinced it was a good idea. Instead, I was simply writing it as a way to +avoid endlessly rehashing similar topics on python-ideas. When someone +broached the subject, they could be pointed at this PEP and told "Come back +when you've read and understood the arguments presented there". Subsequent +discussions (most notably, those surrounding PEP 403's attempt at a more +restricted version of the idea) have convinced me that the idea is valuable +and will help address a number of situations where developers feel that +Python "gets in the way" instead of "matching the way they think". For me, +it is this aspect of "let people express what they're thinking, rather than +forcing them to think differently due to Python's limitations" that finally +allowed the idea to clear the "status quo wins a stalemate" bar ([5]_). -Secondly, Guido van Rossum (or his delegate) will need to accept the PEP. At -the very least, that will not occur until a fully functional draft -implementation for CPython is available, and the other three major Python -implementations (PyPy, Jython, IronPython) have indicated that they consider +However, while I now think the idea is worthwhile, I don't think there is +sufficient time left in the 3.3 release cycle for the idea to mature. A +reference implementation is needed, and people need time to experiment with +that implementation and offer feedback on whether or not it helps with +programming paradigms that are currently somewhat clumsy in Python (like +callback programming). Even if a PEP co-author volunteered immediately to +work on the implementation and incorporate feedback into the PEP text, I feel +targetting 3.3 would be unnecessarily rushing things. So, I've marked this +PEP as a candidate for 3.4 rather than 3.3. + +Once that process is complete, Guido van Rossum (or his delegate) will need +to be sufficiently convinced of the idea's merit and accept the PEP. Such +acceptance will require not only a fully functional reference implementation +for CPython (as already mentioned), but also indications from the other three +major Python implementations (PyPy, Jython, IronPython) that they consider it feasible to implement the proposed semantics once they reach the point of -targetting 3.3 compatibility. Input from related projects with a vested +targetting 3.4 compatibility. Input from related projects with a vested interest in Python's syntax (e.g. Cython) will also be valuable. @@ -69,26 +93,27 @@ Proposal This PEP proposes the addition of an optional ``given`` clause to the syntax for simple statements which may contain an expression, or may -substitute for such an expression for purely syntactic purposes. The +substitute for such a statement for purely syntactic purposes. The current list of simple statements that would be affected by this addition is as follows: -* expression statement -* assignment statement -* augmented assignment statement -* del statement -* return statement -* yield statement -* raise statement -* assert statement -* pass statement + * expression statement + * assignment statement + * augmented assignment statement + * del statement + * return statement + * yield statement + * raise statement + * assert statement + * pass statement The ``given`` clause would allow subexpressions to be referenced by name in the header line, with the actual definitions following in the indented clause. As a simple example:: - c = sqrt(a*a + b*b) given: - a, b = 3, 4 + sorted_data = sorted(data, key=sort_key) given: + def sort_key(item): + return item.attr1, item.attr2 The ``pass`` statement is included to provide a consistent way to skip inclusion of a meaningful expression in the header line. While this is not @@ -150,7 +175,8 @@ interim working variables from polluting the resulting namespace. One potentially useful way to think of the proposed clause is as a middle ground between conventional in-line code and separation of an -operation out into a dedicated function. +operation out into a dedicated function, just as an inline while loop may +eventually be factored out into a dedicator generator. Keyword Choice @@ -158,7 +184,7 @@ Keyword Choice This proposal initially used ``where`` based on the name of a similar construct in Haskell. However, it has been pointed out that there -are existing Python libraries (such as Numpy [4]) that already use +are existing Python libraries (such as Numpy [4]_) that already use ``where`` in the SQL query condition sense, making that keyword choice potentially confusing. @@ -175,6 +201,176 @@ statement would look similar but do completely different things. That way lies C++ and Perl :) +Anticipated Objections +====================== + + +Two Ways To Do It +----------------- + +A lot of code may now be written with values defined either before the +expression where they are used or afterwards in a ``given`` clause, creating +two ways to do it, perhaps without an obvious way of choosing between them. + +On reflection, I feel this is a misapplication of the "one obvious way" +aphorism. Python already offers *lots* of ways to write code. We can use +a for loop or a while loop, a functional style or an imperative style or an +object oriented style. The language, in general, is designed to let people +write code that matches the way they think. Since different people think +differently, the way they write their code will change accordingly. + +Such stylistic questions in a code base are rightly left to the development +group responsible for that code. When does an expression get so complicated +that the subexpressions should be taken out and assigned to variables, even +though those variables are only going to be used once? When should an inline +while loop be replaced with a generator that implements the same logic? +Opinions differ, and that's OK. + +However, explicit PEP 8 guidance will be needed for CPython and the standard +library, and that is discussed below. + + +Out of Order Execution +---------------------- + +The ``given`` clause makes execution jump around a little strangely, as the +body of the ``given`` clause is executed before the simple statement in the +clause header. The closest any other part of Python comes to this is the out +of order evaluation in list comprehensions, generator expressions and +conditional expressions and the delayed application of decorator functions to +the function they decorate (the decorator expressions themselves are executed +in the order they are written). + +While this is true, the syntax is intended for cases where people are +themselves *thinking* about a problem out of sequence (at least as far as +the language is concerned). As an example of this, consider the following +thought in the mind of a Python user: + + I want to sort the items in this sequence according to the values of + attr1 and attr2 on each item. + +If they're comfortable with Python's ``lambda`` expressions, then they might +choose to write it like this:: + + sorted_list = sorted(original, key=(lambda v: v.attr1, v.attr2)) + +That gets the job done, but it hardly reaches the standard of ``executable +pseudocode`` that Python aspires to, does it? + +If they don't like ``lambda`` specifically, the ``operator`` module offers an +alternative that still allows the key function to be defined inline:: + + sorted_list = sorted(original, + key=operator.attrgetter(v. 'attr1', 'attr2')) + +Again, it gets the job done, but executable pseudocode it ain't. + +If they think both of the above options are ugly and confusing, or they need +logic in their key function that can't be expressed as an expression (such +as catching an exception), then Python currently forces them to reverse the +order of their original thought and define the sorting criteria first:: + + def sort_key(item): + return item.attr1, item.attr2 + + sorted_list = sorted(original, key=sort_key) + +"Just define a function" has been the rote response to requests for multi-line +lambda support for years. As with the above options, it gets the job done, +but it really does represent a break between what the user is thinking and +what the language allows them to express. + +I believe the proposal in this PEP will finally let Python get close to the +"executable pseudocode" bar for the kind of thought expressed above:: + + sorted_list = sorted(original, key=sort_key) given: + def sort_key(item): + return item.attr1, item.attr2 + +Everything is in the same order as it was in the user's original thought, the +only addition they have to make is to give the sorting criteria a name so that +the usage can be linked up to the subsequent definition. + +One other useful note on this front, is that this PEP allows existing out of +order execution constructs to be described as special cases of the more +general out of order execution syntax (just as comprehensions are now special +cases of the more general generator expression syntax, even though list +comprehensions existed first):: + + @classmethod + def classname(cls): + return cls.__name__ + +Would be roughly equivalent to:: + + classname = f1(classname) given: + f1 = classmethod + def classname(cls): + return cls.__name__ + +A list comprehension like ``squares = [x*x for x in range(10)]`` +would be equivalent to:: + + # Note: this example uses an explicit early binding variant that + # isn't yet reflected in the rest of the PEP. It will get there, though. + squares = seq given outermost=range(10): + seq = [] + for x in outermost: + seq.append(x*x) + + +Harmful to Introspection +------------------------ + +Poking around in module and class internals is an invaluable tool for +white-box testing and interactive debugging. The ``given`` clause will be +quite effective at preventing access to temporary state used during +calculations (although no more so than current usage of ``del`` statements +in that regard). + +While this is a valid concern, design for testability is an issue that +cuts across many aspects of programming. If a component needs to be tested +independently, then a ``given`` statement should be refactored in to separate +statements so that information is exposed to the test suite. This isn't +significantly different from refactoring an operation hidden inside a +function or generator out into its own function purely to allow it to be +tested in isolation. + + +Lack of Real World Impact Assessment +------------------------------------ + +The examples in the current PEP are almost all relatively small "toy" +examples. The proposal in this PEP needs to be subjected to the test of +application to a large code base (such as the standard library or a large +Twisted application) in a search for examples where the readability of real +world code is genuinely enhanced. + +This is more of a deficiency in the PEP rather than the idea, though. + + +New PEP 8 Guidelines +==================== + +As discussed on python-ideas ([7]_, [9]_) new PEP 8 guidelines would also +need to be developed to provide appropriate direction on when to use the +``given`` clause over ordinary variable assignments. + +Based on the similar guidelines already present for ``try`` statements, this +PEP proposes the following additions for ``given`` statements to the +"Programming Conventions" section of PEP 8: + + - for code that could reasonably be factored out into a separate function, + but is not currently reused anywhere, consider using a ``given`` clause. + This clearly indicates which variables are being used only to define + subcomponents of another statement rather than to hold algorithm or + application state. + + - keep ``given`` clauses concise. If they become unwieldy, either break + them up into multiple steps or else move the details into a separate + function. + + Syntax Change ============= @@ -202,8 +398,9 @@ New:: assert_stmt: 'assert' test [',' test] [given_clause] given_clause: "given" ":" suite -(Note that expr_stmt in the grammar covers assignment and augmented -assignment in addition to simple expression statements) +(Note that ``expr_stmt`` in the grammar is a slight misnomer, as it covers +assignment and augmented assignment in addition to simple expression +statements) The new clause is added as an optional element of the existing statements rather than as a new kind of compound statement in order to avoid creating @@ -213,6 +410,9 @@ listed so that nonsense like the following is disallowed:: break given: a = b = 1 + import sys given: + a = b = 1 + However, the precise Grammar change described above is inadequate, as it creates problems for the definition of simple_stmt (which allows chaining of multiple single line statements with ";" rather than "\\n"). @@ -348,6 +548,7 @@ would then translate to something like the following:: However, as noted in the abstract, an actual implementation of this idea has never been tried. + Detailed Semantics #1: Early Binding of Variable References ----------------------------------------------------------- @@ -389,17 +590,19 @@ clause. Name in outer scopes will be referenced as normal. This intention is subject to revision based on feedback and practicalities of implementation. + Detailed Semantics #2: Handling of ``nonlocal`` and ``global`` -------------------------------------------------------------- ``nonlocal`` and ``global`` will largely operate as if the anonymous functions were defined as in the expansion above. However, they will also -override the default early-binding semantics from names from the containing +override the default early-binding semantics for names from the containing scope. This intention is subject to revision based on feedback and practicalities of implementation. + Detailed Semantics #3: Handling of ``break`` and ``continue`` ------------------------------------------------------------- @@ -408,6 +611,7 @@ defined as in the expansion above. They will be syntax errors if they occur in the ``given`` clause suite but will work normally if they appear within a ``for`` or ``while`` loop as part of that suite. + Detailed Semantics #4: Handling of ``return`` and ``yield`` ------------------------------------------------------------- @@ -416,6 +620,45 @@ suite and will be syntax errors if they occur. They will work normally if they appear within a ``def`` statement within that suite. +Alternative Semantics for Name Binding +-------------------------------------- + +The "early binding" semantics proposed for the ``given`` clause are driven +by the desire to have ``given`` clauses work "normally" in class scopes (that +is, allowing them to see the local variables in the class, even though classes +do not participate in normal lexical scoping). + +There is an alternative, which is to simply declare that the ``given`` clause +creates an ordinary nested scope, just like comprehensions and generator +expressions. Thus, the given clause would share the same quirks as those +constructs: they exhibit surprising behaviour at class scope, since they +can't see the local variables in the class definition. While this behaviour +is considered desirable for method definitions (where class variables are +accessed via the class or instance argument passed to the method), it can be +surprising and inconvenient for implicit scopes that are designed to hide +their own name bindings from the containing scope rather than vice-versa. + +A third alternative, more analogous to the comprehension case (where the +outermost iterator expression is evaluated in the current scope and hence can +see class locals normally), would be to allow *explicit* early binding in the +``given`` clause, by passing an optional tuple of assignments after the +``given`` keyword:: + + # Explicit early binding via given clause + seq = [] + for i in range(10): + seq.append(f) given i=i: + def f(): + return i + assert [f() for f in seq] == list(range(10)) + +(Note: I actually like the explicit early binding idea significantly more +than I do the implicit early binding - expect a future version of the PEP +to be updated accordingly. I've already used it above when describing how +an existing construct like a list comprehension could be expressed as a +special case of the new syntax) + + Examples ======== @@ -426,6 +669,17 @@ Defining "one-off" classes which typically only have a single instance:: ... # However many lines public_name = public_name(*params) + # Current Python (custom decorator) + def singleton(*args, **kwds): + def decorator(cls): + return cls(*args, **kwds) + return decorator + + @singleton(*params) + class public_name(): + ... # However many lines + public_name = public_name(*params) + # Becomes: public_name = MeaningfulClassName(*params) given: class MeaningfulClassName(): @@ -465,57 +719,21 @@ Replacing default argument hack (from functools.lru_cache):: # nested functions, that isn't entirely clear in the current code. -Anticipated Objections -====================== - -* Two Ways To Do It: a lot of code may now be written with values - defined either before the expression where they are used or - afterwards in a ``given`` clause, creating two ways to do it, - without an obvious way of choosing between them. - -* Out of Order Execution: the ``given`` clause makes execution - jump around a little strangely, as the body of the ``given`` - clause is executed before the simple statement in the clause - header. The closest any other part of Python comes to this - is the out of order evaluation in list comprehensions, - generator expressions and conditional expressions. - -* Harmful to Introspection: poking around in module and class internals - is an invaluable tool for white-box testing and interactive debugging. - The ``given`` clause will be quite effective at preventing access to - temporary state used during calculations (although no more so than - current usage of ``del`` statements in that regard) - -These objections should not be dismissed lightly - the proposal -in this PEP needs to be subjected to the test of application to -a large code base (such as the standard library) in a search -for examples where the readability of real world code is genuinely -enhanced. - -New PEP 8 guidelines would also need to be developed to provide -appropriate direction on when to use the ``given`` clause over -ordinary variable assignments. Some thoughts on possible guidelines are -provided at [7] - - Possible Additions ================== * The current proposal allows the addition of a ``given`` clause only for simple statements. Extending the idea to allow the use of - compound statements would be quite possible, but doing so raises + compound statements would be quite possible (by appending the given + clause as an independent suite at the end), but doing so raises serious readability concerns (as values defined in the ``given`` clause may be used well before they are defined, exactly the kind of readability trap that other features like decorators and ``with`` statements are designed to eliminate) -* Currently only the outermost clause of comprehensions and generator - expressions can reference the surrounding namespace when executed - at class level. If this proposal is implemented successfully, the - associated namespace semantics could allow that restriction to be - lifted. There would be backwards compatibility implications in doing - so as existing code may be relying on the behaviour of ignoring - class level variables, but the idea is worth considering. +* The "explicit early binding" variant may be applicable to the discussions + on python-ideas on how to eliminate the default argument hack. A ``given`` + clause in the header line for functions may be the answer to that question. Reference Implementation @@ -525,41 +743,6 @@ None as yet. If you want a crash course in Python namespace semantics and code compilation, feel free to try ;) -Key Concern -=========== - -If a decision on the acceptance or rejection of this PEP had to be made -immediately, rejection would be far more likely. Unlike the previous -major syntax addition to Python (PEP 343's ``with`` statement), this -PEP as yet has no "killer application" of common code that is clearly and -obviously improved through the use of the new syntax. The ``with`` statement -(in conjunction with the generator enhancements in PEP 342) allowed -exception handling to be factored out into context managers in a way -that had never before been possible. Code using the new statement was -not only easier to read, but much easier to write correctly in the -first place. - -In the case of this PEP. however, the "Two Ways to Do It" objection is a -strong one. While the ability to break out subexpresions of a statement -without having to worry about name clashes with the rest of a -function or script and without distracting from the operation that is -the ultimate aim of the statement is potentially nice to have as a -language feature, it doesn't really provide significant expressive power -over and above what is already possible by assigning subexpressions to -ordinary local variables before the statement of interest. In particular, -explaining to new Python programmers when it is best to use a ``given`` -clause and when to use normal local variables is likely to be challenging -and an unnecessary distraction. - -"It might be kinda, sorta, nice to have, sometimes" really isn't a strong -argument for a new syntactic construct (particularly one this complicated). -"Status quo wins a stalemate" [5] is a very useful design principle, and I'm -not yet convinced that this PEP clears that hurdle. - -The case for it has definitely strengthened over time though, which is why -this PEP remains Deferred rather than Rejected. - - TO-DO ===== @@ -571,19 +754,32 @@ TO-DO References ========== -.. [1] http://mail.python.org/pipermail/python-ideas/2010-June/007476.html +.. [1] Explicitation lines in Python: + http://mail.python.org/pipermail/python-ideas/2010-June/007476.html -.. [2] http://mail.python.org/pipermail/python-ideas/2010-July/007584.html +.. [2] 'where' statement in Python: + http://mail.python.org/pipermail/python-ideas/2010-July/007584.html -.. [3] http://mail.python.org/pipermail/python-ideas/2009-July/005132.html +.. [3] Where-statement (Proposal for function expressions): + http://mail.python.org/pipermail/python-ideas/2009-July/005132.html -.. [4] http://mail.python.org/pipermail/python-ideas/2010-July/007596.html +.. [4] Name conflict with NumPy for 'where' keyword choice: + http://mail.python.org/pipermail/python-ideas/2010-July/007596.html -.. [5] http://www.boredomandlaziness.org/2011/02/status-quo-wins-stalemate.html +.. [5] The "Status quo wins a stalemate" design principle: + http://www.boredomandlaziness.org/2011/02/status-quo-wins-stalemate.html -.. [6] http://mail.python.org/pipermail/python-ideas/2011-April/009863.html +.. [6] Assignments in list/generator expressions: + http://mail.python.org/pipermail/python-ideas/2011-April/009863.html -.. [7] http://mail.python.org/pipermail/python-ideas/2011-April/009869.html +.. [7] Possible PEP 3150 style guidelines (#1): + http://mail.python.org/pipermail/python-ideas/2011-April/009869.html + +.. [8] Discussion of PEP 403 (statement local function definition): + http://mail.python.org/pipermail/python-ideas/2011-October/012276.html + +.. [9] Possible PEP 3150 style guidelines (#2): + http://mail.python.org/pipermail/python-ideas/2011-October/012341.html Copyright =========