updates to PEP 318 from Kevin Smith, including PEP title
This commit is contained in:
parent
5cf7e0227a
commit
a2339f1b61
|
@ -117,7 +117,7 @@ Index by Category
|
|||
S 314 Metadata for Python Software Packages v1.1 Kuchling
|
||||
S 315 Enhanced While Loop Carroll
|
||||
S 317 Eliminate Implicit Exception Instantiation Taschuk
|
||||
S 318 Function Modifier Syntax Smith
|
||||
S 318 Function/Method Decorator Syntax Smith
|
||||
S 754 IEEE 754 Floating Point Special Values Warnes
|
||||
|
||||
Finished PEPs (done, implemented in CVS)
|
||||
|
@ -328,7 +328,7 @@ Numerical Index
|
|||
S 315 Enhanced While Loop Carroll
|
||||
SD 316 Programming by Contract for Python Way
|
||||
S 317 Eliminate Implicit Exception Instantiation Taschuk
|
||||
S 318 Function Modifier Syntax Smith
|
||||
S 318 Function/Method Decorator Syntax Smith
|
||||
SR 666 Reject Foolish Indentation Creighton
|
||||
S 754 IEEE 754 Floating Point Special Values Warnes
|
||||
|
||||
|
|
106
pep-0318.txt
106
pep-0318.txt
|
@ -1,5 +1,5 @@
|
|||
PEP: 318
|
||||
Title: Function Modifier Syntax
|
||||
Title: Function/Method Decorator Syntax
|
||||
Version: $Revision$
|
||||
Last-Modified: $Date$
|
||||
Author: Kevin D. Smith <Kevin.Smith@theMorgue.org>
|
||||
|
@ -8,7 +8,7 @@ Type: Standards Track
|
|||
Content-Type: text/plain
|
||||
Created: 05-Jun-2003
|
||||
Python-Version: 2.4
|
||||
Post-History:
|
||||
Post-History: 09-Jun-2003
|
||||
|
||||
|
||||
Abstract
|
||||
|
@ -36,11 +36,16 @@ Motivation
|
|||
15 lines or so, the translation into a class method is not
|
||||
obvious. A solution to this problem is to move the translation
|
||||
of the method to the same point as the method's declaration.
|
||||
The proposed syntax, shown in the example below, is discussed
|
||||
in the following sections.
|
||||
|
||||
def foo(self) as synchronized(lock), classmethod:
|
||||
perform method operation
|
||||
|
||||
|
||||
Proposal
|
||||
|
||||
Probably the simplest way to place the function that translates
|
||||
Probably the simplest way to place the decorator that translates
|
||||
an instance method to a class/static method is illustrated in the
|
||||
code below.
|
||||
|
||||
|
@ -58,7 +63,7 @@ Proposal
|
|||
'def' and the actual name of the method is simply a reference to
|
||||
a callable object that returns a new function reference.
|
||||
This syntax could also be extended to allow multiple function
|
||||
modifiers in the form of a space delimited list as follows:
|
||||
decorators in the form of a space delimited list as follows:
|
||||
|
||||
def protected classmethod foo(self):
|
||||
perform method operation
|
||||
|
@ -71,46 +76,103 @@ Proposal
|
|||
|
||||
While this syntax is simple and easy to read, it does become
|
||||
cluttered and more obscure if you wish to allow arguments to be
|
||||
sent to the function modifier.
|
||||
sent to the function decorator.
|
||||
|
||||
def synchronized(lock) classmethod foo(self):
|
||||
perform method operation
|
||||
def synchronized(lock) classmethod foo(self):
|
||||
perform method operation
|
||||
|
||||
Various syntaxes have been proposed in comp.lang.python. The
|
||||
Instead of placing the decorators in front of the function name,
|
||||
a better place might be after it, as shown below. The word 'as' is
|
||||
added simply as a separator to assist in readability.
|
||||
|
||||
def foo(self) as synchronized(lock), classmethod:
|
||||
perform method operation
|
||||
|
||||
This syntax is quite clear and could probably be interpreted
|
||||
by those not familiar with Python. The proposed syntax can be
|
||||
generalized as follows:
|
||||
|
||||
'def' NAME '(' PARAMETERS ')' ['as' DECORATORS] ':'
|
||||
|
||||
where DECORATORS is a comma-separated list of expressions,
|
||||
or a tuple.
|
||||
|
||||
Other syntaxes have been proposed in comp.lang.python. The
|
||||
most common are demonstrated below.
|
||||
|
||||
def foo(self) [synchronized(lock), classmethod]:
|
||||
perform method operation
|
||||
|
||||
def foo(self) {'pre': synchronized(lock), 'classmethod': True}:
|
||||
""" Skip Montanaro syntax """
|
||||
def foo(self) (synchronized(lock), classmethod):
|
||||
perform method operation
|
||||
|
||||
def foo(self) {'pre': synchronized(lock), 'classmethod': True}:
|
||||
perform method operation
|
||||
|
||||
These three forms use syntax that just seems arbitrary and which
|
||||
does not help the user to comprehend the meaning of it. In
|
||||
addition, since the order in which the decorators are applied
|
||||
may matter, the third, dictionary-style, syntax must be
|
||||
eliminated.
|
||||
|
||||
|
||||
Implementation Issues
|
||||
|
||||
In the following example there are two function decorators:
|
||||
synchronized(lock) and classmethod.
|
||||
|
||||
def foo(self) as synchronized(lock), classmethod:
|
||||
""" Gerrit Holl syntax """
|
||||
perform method operation
|
||||
|
||||
I have a strong preference for the last of the three. The first
|
||||
two use syntax that just seems arbitrary which does not help the
|
||||
user to understand the meaning of it. The third method is very
|
||||
readable and could probably be interpreted easily by those not
|
||||
familiar with Python.
|
||||
Since these all appear within the operation of the 'def'
|
||||
itself, it makes sense that synchronized, lock, and
|
||||
classmethod must exist at the time that the definition
|
||||
is compiled. In addition, each of these arguments will be
|
||||
evaluated before being applied to the compiled function.
|
||||
This means that arguments like synchronized(lock) must
|
||||
return a descriptor that will be applied to foo. Therefore,
|
||||
the code above translates to:
|
||||
|
||||
def foo(self):
|
||||
perform method operation
|
||||
foo = classmethod(<returned-descriptor>(foo))
|
||||
|
||||
In the example above, <returned-descriptor> refers to the
|
||||
descriptor returned by evaluating synchronized(lock).
|
||||
|
||||
It could easily be argued that the descriptors should be applied
|
||||
in reverse order to make the application of the descriptor look
|
||||
more like the resultant code. I tend to prefer this form.
|
||||
|
||||
def foo(self):
|
||||
perform method operation
|
||||
foo = <returned-descriptor>(classmethod(foo))
|
||||
|
||||
In either case, the modified function is bound to the function
|
||||
name at compile time.
|
||||
|
||||
|
||||
Possible Extensions
|
||||
|
||||
The proposed syntax is general enough that it could be used
|
||||
on class definitions as well as shown below.
|
||||
|
||||
class foo(object) as classmodifier:
|
||||
class definition here
|
||||
|
||||
However, there are no obvious parallels for use with other
|
||||
descriptors such as property().
|
||||
|
||||
|
||||
Conclusion
|
||||
|
||||
The current method of translating an instance method to a class
|
||||
or static method is awkward. A new syntax for applying function
|
||||
modifiers should be implemented (proposed syntax shown below).
|
||||
decorators should be implemented (proposed syntax shown below).
|
||||
|
||||
def foo(self) as synchronized(lock), classmethod:
|
||||
perform method operation
|
||||
|
||||
More generally,
|
||||
|
||||
def foo(self) as <tuple>:
|
||||
perform method operation
|
||||
|
||||
The proposed syntax is simple, powerful, easy to read, and
|
||||
therefore preserves those qualities of the Python language.
|
||||
|
||||
|
|
Loading…
Reference in New Issue