Update to PEP 232

Barry A. Warsaw barry at digicool.com
Tue Feb 20 21:22:32 CET 2001


After some internal discussions amongst the Pythonlabbers, we've had
to make some updates to PEP 232, Function Attributes.  Attached is the
complete current PEP draft, also available at

    http://python.sourceforge.net/peps/pep-0232.html

The PEP has been moved back to Draft status, but will be Accepted and
Finalized for Python 2.1.  It will also be propagated forward for
Python 2.2 for the next step in implementation.

-Barry

-------------------- snip snip --------------------
PEP: 232
Title: Function Attributes
Version: $Revision: 1.6 $
Author: barry at digicool.com (Barry A. Warsaw)
Status: Draft
Type: Standards Track
Created: 02-Dec-2000
Python-Version: 2.1 / 2.2
Post-History: 20-Feb-2001


Introduction

    This PEP describes an extension to Python, adding attribute
    dictionaries to functions and methods.  This PEP tracks the status
    and ownership of this feature.  It contains a description of the
    feature and outlines changes necessary to support the feature.
    This PEP summarizes discussions held in mailing list forums, and
    provides URLs for further information, where appropriate.  The CVS
    revision history of this file contains the definitive historical
    record.


Background

    Functions already have a number of attributes, some of which are
    writable, e.g. func_doc, a.k.a. func.__doc__.  func_doc has the
    interesting property that there is special syntax in function (and
    method) definitions for implicitly setting the attribute.  This
    convenience has been exploited over and over again, overloading
    docstrings with additional semantics.

    For example, John Aycock has written a system where docstrings are
    used to define parsing rules[1].  Zope's ZPublisher ORB[2] uses
    docstrings to signal "publishable" methods, i.e. methods that can
    be called through the web.  And Tim Peters has developed a system
    called doctest[3], where docstrings actually contain unit tests.

    The problem with this approach is that the overloaded semantics
    may conflict with each other.  For example, if we wanted to add a
    doctest unit test to a Zope method that should not be publishable
    through the web.


Proposal

    This proposal adds a new dictionary to function objects, called
    func_dict (a.k.a. __dict__).  This dictionary can be set and get
    using ordinary attribute set and get syntax.

    Methods also gain `getter' syntax, and they currently access the
    attribute through the dictionary of the underlying function
    object.  It is not possible to set attributes on bound or unbound
    methods, except by doing so explicitly on the underlying function
    object.  See the `Future Directions' discussion below for
    approaches in subsequent versions of Python.

    A function object's __dict__ can also be set, but only to a
    dictionary object (i.e. setting __dict__ to UserDict raises a
    TypeError). 


Examples

    Here are some examples of what you can do with this feature.

        def a():
	    pass

	a.publish = 1
	a.unittest = '''...'''

	if a.publish:
	    print a()

	if hasattr(a, 'unittest'):
	    testframework.execute(a.unittest)

	class C:
	    def a(self):
	        'just a docstring'
            a.publish = 1

	c = C()
	if c.a.publish:
            publish(c.a())


Other Uses

    Paul Prescod enumerated a bunch of other uses:

    http://mail.python.org/pipermail/python-dev/2000-April/003364.html


Future Directions

    - A previous version of this PEP (and the accompanying
      implementation) allowed for both setter and getter of attributes
      on unbound methods, and only getter on bound methods.  A number
      of problems were discovered with this policy.

      Because method attributes were stored in the underlying
      function, this caused several potentially surprising results:

      class C:
          def a(self): pass

      c1 = C()
      c2 = C()
      c1.a.publish = 1
      # c2.a.publish would now be == 1 also!

      Because a change to `a' bound c1 also caused a change to `a'
      bound to c2, setting of attributes on bound methods was
      disallowed.  However, even allowing setting of attributes on
      unbound methods has its ambiguities:

      class D(C): pass
      class E(C): pass

      D.a.publish = 1
      # E.a.publish would now be == 1 also!

      For this reason, the current PEP disallows setting attributes on
      either bound or unbound methods, but does allow for getting
      attributes on either -- both return the attribute value on the
      underlying function object.

      The proposal for Python 2.2 is to implement setting (bound or
      unbound) method attributes by setting attributes on the instance
      or class, using special naming conventions.  I.e.

      class C:
          def a(self): pass

      C.a.publish = 1
      C.__a_publish__ == 1 # true

      c = C()
      c.a.publish = 2
      c.__a_publish__ == 2 # true

      d = C()
      d.__a_publish__ == 1 # true

      Here, a lookup on the instance would look to the instance's
      dictionary first, followed by a lookup on the class's
      dictionary, and finally a lookup on the function object's
      dictionary.

    - Currently, Python supports function attributes only on Python
      functions (i.e. those that are written in Python, not those that
      are built-in).  Should it be worthwhile, a separate patch can be
      crafted that will add function attributes to built-ins.

    - __doc__ is the only function attribute that currently has
      syntactic support for conveniently setting.  It may be
      worthwhile to eventually enhance the language for supporting
      easy function attribute setting.  Here are some syntaxes
      suggested by PEP reviewers:

      def a {
          'publish' : 1,
          'unittest': '''...''',
          }
          (args):
          # ...

      def a(args):
          """The usual docstring."""
          {'publish' : 1,
           'unittest': '''...''',
           # etc.
           }

      It isn't currently clear if special syntax is necessary or
      desirable.


Dissenting Opinion

    When this was discussed on the python-dev mailing list in April
    2000, a number of dissenting opinions were voiced.  For
    completeness, the discussion thread starts here:

    http://mail.python.org/pipermail/python-dev/2000-April/003361.html

    The dissenting arguments appear to fall under the following
    categories:

    - no clear purpose (what does it buy you?)
    - other ways to do it (e.g. mappings as class attributes)
    - useless until syntactic support is included

    Countering some of these arguments is the observation that with
    vanilla Python 2.0, __doc__ can in fact be set to any type of
    object, so some semblance of writable function attributes are
    already feasible.  But that approach is yet another corruption of
    __doc__.

    And while it is of course possible to add mappings to class
    objects (or in the case of function attributes, to the function's
    module), it is more difficult and less obvious how to extract the
    attribute values for inspection.

    Finally, it may be desirable to add syntactic support, much the
    same way that __doc__ syntactic support exists.  This can be
    considered separately from the ability to actually set and get
    function attributes.


Reference Implementation

    The reference implementation is available on SourceForge as a
    patch against the Python CVS tree (patch #103123).  This patch
    doesn't include the regrtest module and output file.  Those are
    available upon request.

   http://sourceforge.net/patch/?func=detailpatch&patch_id=103123&group_id=5470

    This patch has been applied and will become part of Python 2.1.


References

    [1] Aycock, "Compiling Little Languages in Python",
    http://www.foretec.com/python/workshops/1998-11/proceedings/papers/aycock-little/aycock-little.html

    [2] http://classic.zope.org:8080/Documentation/Reference/ORB

    [3] ftp://ftp.python.org/pub/python/contrib-09-Dec-1999/System/doctest.py
    

Copyright

    This document has been placed in the Public Domain.



Local Variables:
mode: indented-text
indent-tabs-mode: nil
End:




More information about the Python-list mailing list