[Python-checkins] python/nondist/peps pep-0318.txt,1.4,1.5

montanaro at users.sourceforge.net montanaro at users.sourceforge.net
Tue Mar 23 11:41:19 EST 2004


Update of /cvsroot/python/python/nondist/peps
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv2332

Modified Files:
	pep-0318.txt 
Log Message:
Checking in what we have so far.  Still digesting some of Jim Jewett's
inputs.



Index: pep-0318.txt
===================================================================
RCS file: /cvsroot/python/python/nondist/peps/pep-0318.txt,v
retrieving revision 1.4
retrieving revision 1.5
diff -C2 -d -r1.4 -r1.5
*** pep-0318.txt	28 Feb 2004 19:09:44 -0000	1.4
--- pep-0318.txt	23 Mar 2004 16:41:17 -0000	1.5
***************
*** 3,243 ****
  Version: $Revision$
  Last-Modified: $Date$
! Author: Kevin D. Smith <Kevin.Smith at theMorgue.org>
  Status: Draft
  Type: Standards Track
! Content-Type: text/plain
  Created: 05-Jun-2003
  Python-Version: 2.4
! Post-History: 09-Jun-2003, 10-Jun-2003, 27-Feb-2004
  
  
  Abstract
      
!     The current method for declaring class and static methods
!     is awkward and can lead to code that is difficult to understand.
!     This PEP introduces possible new syntax which will place the
!     translation of instance methods to class/static methods at
!     the same point in the code as the method's declaration. 
  
  
  Motivation
  
!     The current method of translating an instance method into a 
!     class/static method places the actual translation at a different
!     point in the code than the declaration of the method.  The 
!     code below demonstrates this.
  
!         def foo(self):
!             perform method operation
!         foo = classmethod(foo)
  
!     When the method is very short, it is easy to look ahead and see
!     that this is a class method.  However, if the method is more than
!     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 decorator that translates
!     an instance method to a class/static method is illustrated in the
!     code below.
  
!         def classmethod foo(self):
!             perform method operation 
  
!     The code in this example will simply perform the following.
  
!         def foo(self):
!             perform method operation
!         foo = classmethod(foo)
!      
!     This syntax does not introduce any new keywords and is completely
!     backwards compatible with any existing code.  The word between the
!     '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 
!     decorators in the form of a space delimited list as follows:
  
!        def protected classmethod foo(self):
!            perform method operation 
  
!     which would be equivalent to the current form:
  
!        def foo(self):
!            perform method operation
!        foo = protected(classmethod(foo))
  
!     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 decorator.
  
!         def synchronized(lock) classmethod foo(self):
!             perform method operation 
  
!     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.  Using the latter form, the last example above 
!     would look like:
  
!         def foo(self) as (synchronized(lock), classmethod):
!             perform method operation
  
!     This form make is possible for the list of decorators to
!     span multiple lines without using the line continuation operator.
  
! Alternate Syntaxes
  
!     Other syntaxes have been proposed in comp.lang.python and 
!     python-dev.  Unfortunately, no one syntax has come out as a clear
!     winner in the lengthy discussions.  The most common suggestions
!     are demonstrated below.  The proposed syntax is also included
!     for easy comparison.
  
!     Proposed Syntax
  
!         def foo(self) as synchronized(lock), classmethod:
!             perform method operation
  
!         def foo(self) as (synchronized(lock), classmethod):
!             perform method operation
  
!     Prefix Forms
  
!         def [synchronized(lock), classmethod] foo(self):
!             perform method operation
  
!         def synchronized(lock), classmethod foo(self):
!             perform method operation
  
!         # Same as above, but only identifiers are allowed
!         sync = synchronized(lock)
!         def sync, classmethod foo(self):
!             perform method operation
  
!         # Java-like
!         sync = synchronized(lock)
!         def @sync @classmethod foo(self):
!             perform method operation
  
!     Postfix Forms
  
!         def foo(self) [synchronized(lock), classmethod]:
!             perform method operation
  
!         def foo(self) (synchronized(lock), classmethod):
!             perform method operation
  
!         def foo(self) {'pre': synchronized(lock), 'classmethod': True}:
!             perform method operation
  
!     I'm not as fond of the forms that use '[ ]' since code like
!     'foo()[a]' looks as if you are getting the item 'a' from 'foo()'.
!     Although, this isn't as much of an issue when using '[ ]' in
!     a prefix form.  The Java-like syntax adds new syntax that is 
!     very arbitrary and is almost Perl-ish.  In addition, since the 
!     order in which the decorators are applied may matter, the last,
!     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:
!             perform method operation
  
!     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 executed.  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 when the 'def' statement is executed.
  
! Open Issues
  
!     It is not clear at the moment if it is even possible to have
!     multiple decorators for a function.  If decorators are required
!     to take a function/method and return a descriptor, it might 
!     not even be possible to wrap multiple decorators.  This should
!     be explored since the best syntax for multiple decorators
!     may not be the same as the best syntax for a single decorator.
  
! Current Implementations
  
!     I am not personally familiar enough with Python's source to
!     implement the proposed syntax; however, Michael Hudson has 
!     implemented the "square-bracketed" syntax (see patch at
!     http://starship.python.net/crew/mwh/hacks/meth-syntax-sugar.diff).
!     It should be fairly simple for the Python development team
!     to translate this patch to the proposed syntax.
  
  
! 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
!     decorators should be implemented (proposed syntax shown below).  
  
!         def foo(self) as synchronized(lock), classmethod:
!             perform method operation
  
!     The proposed syntax is simple, powerful, easy to read, and 
!     therefore preserves those qualities of the Python language.
  
  
  Copyright
  
!     This document has been placed in the public domain.
  
  
--- 3,281 ----
  Version: $Revision$
  Last-Modified: $Date$
! Author: Kevin D. Smith <Kevin.Smith at theMorgue.org>, 
!         Jim Jewett <jimjjewett at users.sourceforge.net>,
!         Skip Montanaro <skip at pobox.com>
  Status: Draft
  Type: Standards Track
! Content-Type: text/x-rst
  Created: 05-Jun-2003
  Python-Version: 2.4
! Post-History: 09-Jun-2003, 10-Jun-2003, 27-Feb-2004, 23-Mar-2004
  
  
  Abstract
+ ========
      
! The current method for declaring class and static methods is awkward 
! and can lead to code that is difficult to understand.  Ideally, these 
! transformations should be made at the same point in the code where the 
! declaration itself is made.  This PEP introduces new syntax for 
! transformations of a declaration.
  
  
  Motivation
+ ==========
  
! The current method of applying a transformation to a function or
! method places the actual translation after the function body.  For
! large functions this separates a key component of the function's
! behavior from the definition of the rest of the function's external
! interface.  For example::
  
!     def foo(self):
!         perform method operation
!     foo = classmethod(foo)
  
! This becomes less readable with longer methods.  It also seems less
! than pythonic to name the function three times for what is
! conceptually a single declaration.  A solution to this problem is to
! move the transformation of the method closer to the method's own
! declaration.  While the new syntax is not yet final, the intent is to
! replace::
  
!     def foo(cls):
!         pass
!     foo = synchronized(lock)(foo)
!     foo = classmethod(foo)
  
+ with an alternative that places the decoration in the function's
+ declaration::
  
!     def foo(cls) using [synchronized(lock), classmethod]:
!         pass
  
! Background
! ==========
  
! There is general agreement that syntactic support is desirable to the
! current state of affairs.  Guido mentioned `syntactic support for
! decorators`_ in his DevDay keynote presentation at the `10th Python
! Conference`_, though `he later said`_ it was only one of several
! extensions he proposed there "semi-jokingly".  `Michael Hudson raised
! the topic`_ on ``python-dev`` shortly after the conference,
! attributing the bracketed syntax to an earlier proposal on
! ``comp.lang.python`` by `Gareth
! McCaughan`_.
  
! .. _syntactic support for decorators: http://www.python.org/doc/essays/ppt/python10/py10keynote.pdf
! .. _10th python conference: http://www.python.org/workshops/2002-02/
! .. _michael hudson raised the topic: http://mail.python.org/pipermail/python-dev/2002-February/020005.html
! .. _he later said: http://mail.python.org/pipermail/python-dev/2002-February/020017.html
! .. _gareth mccaughan: http://groups.google.com/groups?hl=en&lr=&ie=UTF-8&oe=UTF-8&selm=slrna40k88.2h9o.Gareth.McCaughan%40g.local
  
! Design Goals
! ============
  
! The new syntax should
  
! *  work for arbitrary wrappers, including user-defined callables and
!    the existing builtins ``classmethod()`` and ``staticmethod``
  
! *  work with multiple wrappers per definition
  
! *  make it obvious what is happening; at the very least it should be 
!    obvious that new users can safely ignore it when writing their own 
!    code
  
! *  not make future extensions more difficult
  
! *  be easy to type;  programs that use it are expected to use it very 
!    frequently
  
! *  not make it more difficult to scan through code quickly.  It should 
!    still be easy to search for all definitions, a particular 
!    definition, or the arguments that a function accepts
  
! *  not needlessly complicate secondary support tools such as
!    language-sensitive editors and other "`toy parser tools out
!    there`_"
  
! .. _toy parser tools out there: http://groups.google.com/groups?hl=en&lr=&ie=UTF-8&oe=UTF-8&selm=mailman.1010809396.32158.python-list%40python.org
  
! Proposed Syntax
! ===============
  
! The currently proposed syntax is::
  
!     def func(arg1, arg2, ...) [dec1, dec2, ...]:
!         pass
  
! The decorators are near the declaration of the function's API but are
! clearly secondary.  The square brackets make it possible to fairly
! easily break long lists of decorators across multiple lines.
  
! Alternate Proposals
! ===================
  
! A few other syntaxes have been proposed::
  
!     def func(arg1, arg2, ...) as dec1, dec2, ...:
!         pass
  
! The absence of brackets makes it cumbersome to break long lists of
! decorators across multiple lines.  The keyword "as" doesn't have the
! same meaning as its use in the ``import`` statement.
  
! ::
  
!     def [dec1, dec2, ...] func(arg1, arg2, ...):
!         pass
  
! This form has the disadvantage that the decorators become visually
! higher priority than the function name and argument list.
  
! ::
  
!     def func [dec1, dec2, ...] (arg1, arg2, ...):
!         pass
  
! Quixote's Page Template Language uses this form, but only supports a
! single decorator chosen from a restricted set.  For short lists it
! works okay, but for long list it separates the argument list from the
! function name.
  
! ::
  
!     using:
!         dec1
!         dec2
!         ...
!     def foo(arg1, arg2, ...):
!         pass
  
! The function definition is not nested within the using: block making
! it impossible to tell which objects following the block will be
! decorated.  Nesting the function definition within the using: block
! suggests block structure that doesn't exist.  The name ``foo`` would
! actually exist at the same scope as the using: block.  Finally, it
! would require the introduction of a new keyword.
  
! Current Implementation
! ======================
  
! Michael Hudson has posted a `patch`_ at Starship, which implements the
! proposed syntax and left-first application of decorators::
  
!     def func(arg1, arg2, ...) [dec1, dec2]:
!         pass
  
! is equivalent to::
  
!     def func(arg1, arg2, ...):
!         pass
!     func = dec2(dec1(func))
  
! though without the intermediate creation of a variable named ``func``.
  
! .. _patch: http://starship.python.net/crew/mwh/hacks/meth-syntax-sugar.diff
  
! Examples
! ========
  
! Much of the discussion on ``comp.lang.python`` and the ``python-dev``
! mailing list focuses on the use of the ``staticmethod()`` and
! ``classmethod()`` builtins.  This capability is much more powerful
! than that.  This section presents some examples of use.
  
! 1. Define a function to be executed at exit.  Note that the function
!    isn't actually "wrapped" in the usual sense.
  
! ::
  
!     def onexit(f):
!         import atexit
!         atexit.register(f)
!         return f
  
+     def func() [onexit]:
+         ...
  
! 2. Define a class with a singleton instance.  Note that once the class
!    disappears enterprising programmers would have to be more creative
!    to create more instances.  (From Shane Hathaway on ``python-dev``.)
  
! ::
  
!     def singleton(cls):
!         return cls()
  
!     class MyClass [singleton]:
!         ...
  
+ 3. Decorate a function with release information.  (Based on an example
+    posted by Anders Munch on ``python-dev``.)
  
! ::
  
!     def release(**kwds):
!         def decorate(f):
!             for k in kwds:
!                 setattr(f, k, kwds[k])
!             return f
!         return decorate
  
!     def classmethod(f) [release(versionadded="2.2",
!                                 author="Guido van Rossum")]:
!         ...
  
! 4. Enforce function argument and return types.
! 
! ::
! 
!     def accepts(*types):
!         def check_accepts(f):
!             def new_f(*args, **kwds):
!                 for (a, t) in zip(args, types):
!                     assert isinstance(a, t), \
!                            "arg %r does not match %s" % (a,t)
!                 return f(*args, **kwds)
!             assert len(types) == f.func_code.co_argcount
!             return new_f
!         return check_accepts
! 
!     def returns(rtype):
!         def check_returns(f):
!             def new_f(*args, **kwds):
!                 result = f(*args, **kwds)
!                 assert isinstance(result, rtype), \
!                        "return value %r does not match %s" % (result,rtype)
!                 return result
!             return new_f
!         return check_returns
! 
!     def func(arg1, arg2) [accepts(int, (int,float)),
!                           returns((int,float))]:
!         return arg1 * arg2
! 
! Of course, all these examples are possible today, though without the
! syntactic support.
! 
! Possible Extensions
! ===================
! 
! The proposed syntax is general enough that it could be used on class
! definitions as well::
! 
!     class foo(object) [dec1, dec2, ...]:
!         class definition here
! 
! Use would likely be much less than function decorators.  The current
! patch only implements function decorators.
  
  
  Copyright
+ =========
  
! This document has been placed in the public domain.
  
  




More information about the Python-checkins mailing list