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 314 Metadata for Python Software Packages v1.1 Kuchling
|
||||||
S 315 Enhanced While Loop Carroll
|
S 315 Enhanced While Loop Carroll
|
||||||
S 317 Eliminate Implicit Exception Instantiation Taschuk
|
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
|
S 754 IEEE 754 Floating Point Special Values Warnes
|
||||||
|
|
||||||
Finished PEPs (done, implemented in CVS)
|
Finished PEPs (done, implemented in CVS)
|
||||||
|
@ -328,7 +328,7 @@ Numerical Index
|
||||||
S 315 Enhanced While Loop Carroll
|
S 315 Enhanced While Loop Carroll
|
||||||
SD 316 Programming by Contract for Python Way
|
SD 316 Programming by Contract for Python Way
|
||||||
S 317 Eliminate Implicit Exception Instantiation Taschuk
|
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
|
SR 666 Reject Foolish Indentation Creighton
|
||||||
S 754 IEEE 754 Floating Point Special Values Warnes
|
S 754 IEEE 754 Floating Point Special Values Warnes
|
||||||
|
|
||||||
|
|
106
pep-0318.txt
106
pep-0318.txt
|
@ -1,5 +1,5 @@
|
||||||
PEP: 318
|
PEP: 318
|
||||||
Title: Function Modifier Syntax
|
Title: Function/Method Decorator Syntax
|
||||||
Version: $Revision$
|
Version: $Revision$
|
||||||
Last-Modified: $Date$
|
Last-Modified: $Date$
|
||||||
Author: Kevin D. Smith <Kevin.Smith@theMorgue.org>
|
Author: Kevin D. Smith <Kevin.Smith@theMorgue.org>
|
||||||
|
@ -8,7 +8,7 @@ Type: Standards Track
|
||||||
Content-Type: text/plain
|
Content-Type: text/plain
|
||||||
Created: 05-Jun-2003
|
Created: 05-Jun-2003
|
||||||
Python-Version: 2.4
|
Python-Version: 2.4
|
||||||
Post-History:
|
Post-History: 09-Jun-2003
|
||||||
|
|
||||||
|
|
||||||
Abstract
|
Abstract
|
||||||
|
@ -36,11 +36,16 @@ Motivation
|
||||||
15 lines or so, the translation into a class method is not
|
15 lines or so, the translation into a class method is not
|
||||||
obvious. A solution to this problem is to move the translation
|
obvious. A solution to this problem is to move the translation
|
||||||
of the method to the same point as the method's declaration.
|
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
|
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
|
an instance method to a class/static method is illustrated in the
|
||||||
code below.
|
code below.
|
||||||
|
|
||||||
|
@ -58,7 +63,7 @@ Proposal
|
||||||
'def' and the actual name of the method is simply a reference to
|
'def' and the actual name of the method is simply a reference to
|
||||||
a callable object that returns a new function reference.
|
a callable object that returns a new function reference.
|
||||||
This syntax could also be extended to allow multiple function
|
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):
|
def protected classmethod foo(self):
|
||||||
perform method operation
|
perform method operation
|
||||||
|
@ -71,46 +76,103 @@ Proposal
|
||||||
|
|
||||||
While this syntax is simple and easy to read, it does become
|
While this syntax is simple and easy to read, it does become
|
||||||
cluttered and more obscure if you wish to allow arguments to be
|
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):
|
def synchronized(lock) classmethod foo(self):
|
||||||
perform method operation
|
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.
|
most common are demonstrated below.
|
||||||
|
|
||||||
def foo(self) [synchronized(lock), classmethod]:
|
def foo(self) [synchronized(lock), classmethod]:
|
||||||
perform method operation
|
perform method operation
|
||||||
|
|
||||||
def foo(self) {'pre': synchronized(lock), 'classmethod': True}:
|
def foo(self) (synchronized(lock), classmethod):
|
||||||
""" Skip Montanaro syntax """
|
|
||||||
perform method operation
|
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:
|
def foo(self) as synchronized(lock), classmethod:
|
||||||
""" Gerrit Holl syntax """
|
|
||||||
perform method operation
|
perform method operation
|
||||||
|
|
||||||
I have a strong preference for the last of the three. The first
|
Since these all appear within the operation of the 'def'
|
||||||
two use syntax that just seems arbitrary which does not help the
|
itself, it makes sense that synchronized, lock, and
|
||||||
user to understand the meaning of it. The third method is very
|
classmethod must exist at the time that the definition
|
||||||
readable and could probably be interpreted easily by those not
|
is compiled. In addition, each of these arguments will be
|
||||||
familiar with Python.
|
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
|
Conclusion
|
||||||
|
|
||||||
The current method of translating an instance method to a class
|
The current method of translating an instance method to a class
|
||||||
or static method is awkward. A new syntax for applying function
|
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:
|
def foo(self) as synchronized(lock), classmethod:
|
||||||
perform method operation
|
perform method operation
|
||||||
|
|
||||||
More generally,
|
|
||||||
|
|
||||||
def foo(self) as <tuple>:
|
|
||||||
perform method operation
|
|
||||||
|
|
||||||
The proposed syntax is simple, powerful, easy to read, and
|
The proposed syntax is simple, powerful, easy to read, and
|
||||||
therefore preserves those qualities of the Python language.
|
therefore preserves those qualities of the Python language.
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue