This PEP is based heavily on many of the ideas in PEP 3150 (Statement Local Namespaces) so some elements of the rationale will be familiar to readers of that PEP. Both PEPs remain deferred for the time being, primarily due to the lack of compelling real world use cases in either PEP.

This new clause is designed to be used whenever a "one-shot" function or class is needed, and placing the function or class definition before the statement that uses it actually makes the code harder to read. It also avoids any name shadowing concerns by making sure the new name is visible only to the statement in the @in clause.

This PEP proposes the addition of a new @in decorator clause that makes it possible to override the name binding step of a function or class definition.

If the repetition of the name seems especially annoying, then a throwaway name like f can be used instead:

That structure is OK when you're using the callable multiple times, but it's irritating to be forced into it for one-off operations.

Before diving into the long history of this problem and the detailed rationale for this specific proposed solution, here are a few simple examples of the kind of code it is designed to simplify.

In a very real sense, this proposal is about making it possible to override the implicit "name = <defined function or class>" name binding operation that is part of every function or class definition, specifically in those cases where the local name binding isn't actually needed.

The name used in the trailing function or class definition is only visible from the associated @in clause, and behaves as if it was an ordinary variable defined in that scope. If any nested scopes are created in either the @in clause or the trailing function or class definition, those scopes will see the trailing function or class definition rather than any other bindings for that name in the containing scope.

The @in clause will not create a new scope - all name binding operations aside from the trailing function or class definition will affect the containing scope.

The @in clause is allowed to contain any simple statement (including those that don't make any sense in that context, such as pass - while such code would be legal, there wouldn't be any point in writing it). This permissive structure is easier to define and easier to explain, but a more restrictive approach that only permits operations that "make sense" would also be possible (see PEP 3150 for a list of possible candidates).

The trailing function or class definition is always named - the name of the trailing definition is then used to make the forward reference from the @in clause.

The new @in clause precedes the decorator lines, and allows forward references to the trailing function or class definition.

This PEP proposes the addition of a new @in clause that is a variant of the existing class and function decorator syntax.

Background The question of "multi-line lambdas" has been a vexing one for many Python users for a very long time, and it took an exploration of Ruby's block functionality for me to finally understand why this bugs people so much: Python's demand that the function be named and introduced before the operation that needs it breaks the developer's flow of thought. They get to a point where they go "I need a one-shot operation that does <X>", and instead of being able to just say that directly, they instead have to back up, name a function to do <X>, then call that function from the operation they actually wanted to do in the first place. Lambda expressions can help sometimes, but they're no substitute for being able to use a full suite. Ruby's block syntax also heavily inspired the style of the solution in this PEP, by making it clear that even when limited to one anonymous function per statement, anonymous functions could still be incredibly useful. Consider how many constructs Python has where one expression is responsible for the bulk of the heavy lifting: comprehensions, generator expressions, map(), filter()

key arguments to sorted(), min(), max()

partial function application

provision of callbacks (e.g. for weak references or asynchronous IO)

array broadcast operations in NumPy However, adopting Ruby's block syntax directly won't work for Python, since the effectiveness of Ruby's blocks relies heavily on various conventions in the way functions are defined (specifically, using Ruby's yield syntax to call blocks directly and the &arg mechanism to accept a block as a function's final argument). Since Python has relied on named functions for so long, the signatures of APIs that accept callbacks are far more diverse, thus requiring a solution that allows one-shot functions to be slotted in at the appropriate location. The approach taken in this PEP is to retain the requirement to name the function explicitly, but allow the relative order of the definition and the statement that references it to be changed to match the developer's flow of thought. The rationale is essentially the same as that used when introducing decorators, but covering a broader set of applications.

Relation to PEP 3150 PEP 3150 (Statement Local Namespaces) describes its primary motivation as being 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. This PEP achieves the same goal in a different way, by allowing the simple name binding of a standard function definition to be replaced with something else (like assigning the result of the function to a value). Despite having the same author, the two PEPs are in direct competition with each other. PEP 403 represents a minimalist approach that attempts to achieve useful functionality with a minimum of change from the status quo. This PEP instead aims for a more flexible standalone statement design, which requires a larger degree of change to the language. Note that where PEP 403 is better suited to explaining the behaviour of generator expressions correctly, this PEP is better able to explain the behaviour of decorator clauses in general. Both PEPs support adequate explanations for the semantics of container comprehensions.

Keyword Choice The proposal definitely requires some kind of prefix to avoid parsing ambiguity and backwards compatibility problems with existing constructs. It also needs to be clearly highlighted to readers, since it declares that the following piece of code is going to be executed only after the trailing function or class definition has been executed. The in keyword was chosen as an existing keyword that can be used to denote the concept of a forward reference. The @ prefix was included in order to exploit the fact that Python programmers are already used to decorator syntax as an indication of out of order execution, where the function or class is actually defined first and then decorators are applied in reverse order. For functions, the construct is intended to be read as "in <this statement that references NAME> define NAME as a function that does <operation>". The mapping to English prose isn't as obvious for the class definition case, but the concept remains the same.

Better Debugging Support for Functions and Classes with Short Names One of the objections to widespread use of lambda expressions is that they have a negative effect on traceback intelligibility and other aspects of introspection. Similar objections are raised regarding constructs that promote short, cryptic function names (including this one, which requires that the name of the trailing definition be supplied at least twice, encouraging the use of shorthand placeholder names like f ). However, the introduction of qualified names in PEP 3155 means that even anonymous classes and functions will now have different representations if they occur in different scopes. For example: >>> def f(): ... return lambda: y ... >>> f() <function f.<locals>.<lambda> at 0x7f6f46faeae0> Anonymous functions (or functions that share a name) within the same scope will still share representations (aside from the object ID), but this is still a major improvement over the historical situation where everything except the object ID was identical.

Possible Implementation Strategy This proposal has at least one titanic advantage over PEP 3150: implementation should be relatively straightforward. The @in clause will be included in the AST for the associated function or class definition and the statement that references it. When the @in clause is present, it will be emitted in place of the local name binding operation normally implied by a function or class definition. The one potentially tricky part is changing the meaning of the references to the statement local function or namespace while within the scope of the in statement, but that shouldn't be too hard to address by maintaining some additional state within the compiler (it's much easier to handle this for a single name than it is for an unknown number of names in a full nested suite).