[Python-Dev] PEP-able

Paul Prescod paul@prescod.net
Thu, 20 Jul 2000 01:35:28 -0500

PEP: ???
Title: Computed Attributes
Version: $Revision: 1.0 $
Owner: paul@prescod.net
Python-Version: 2.0
Status: Incomplete


    This PEP describes a feature to make it easier to use Python
    attribute set/get/del syntax to fetch the results of a computation
    or to invoke computation. This feature has been emulated using
    __getattr__/__setattr__/__delattr__ but this approach suffers 
    severe usability and performance concerns.


    Special methods should declare themselves with declarations of the
    following form:

    class x:
        def __get_foo__(self ): ...  def __set_foo__(self, value ): ...
        def __del_foo__(self ): ...

    They are used like this:

    del x.foo


    References of the sort x.y should be taken, if x is an instance type
    of a class with a __get_y__ method as being equivalent to a call to
    that method. Code that assigns to y should instead call __set_y__
    if that method is defined on x's class. Code that deletes x.y should
    call __del_y__ if that method is defined on x's class.

    It is disallowed to actually have an attribute named y in the
    dictionary for reasons that will become clear when we discuss the

    It is not required that every special method have two more matching
    special methods. If one is declared then the other two operations
    effectively prohibited and will raise an exception. This is an easy
    way to make read-only (or even write-only or delete-only)

    An implementation of __get_y__ takes precedence over an 
    implementation of __getattr__ based on the principle that 
    __getattr__ is supposed to be invoked only after finding an 
    appropriate attribute has failed. This is important for 
    acceptable performance.

    An implementation of __set_y__ takes precedence over an 
    implementation of __setattr__ in order to be consistent. The 
    opposite choice seems fairly feasible also, however. The same 
    goes for __del_y__.

Proposed Implementation

    There is a new object called a computed attribute object. It has
    three attributes: get, set, delete. In PyClass_New, methods of
    the appropriate form will be detected and converted into objects
    (just like unbound method objects).  Matching methods go in the same
    computed attribute object and missing methods are replaced with a
    stub that throws the TypeError. If there are any computed attributes
    at all, a flag is set. Let's call it "I_have_computed_attributes"
    for now.

    A get proceeds as usual until just before the object is returned.
    In addition to the current check whether the returned object is a
    method it would also check whether a returned object is a computed
    attribute.  If so, it would invoke the getter method and return
    the value. To remove a computed attribute object you could directly
    fiddle with the dictionary.

    A set proceeds by checking the "I_have_computed_attributes" flag. If
    it is not set, everything proceeds as it does today. If it is set
    then we must do a dictionary get on the requested object name. If it
    returns a computed method attribute then we call the setter function
    with the value. If it returns any other object then we discard the
    result and continue as we do today.

    The I_have_computed_attributes flag is intended to eliminate the
    performance degradation of an extra "get" per "set" for objects not
    using this feature. You might note that I have not proposed any
    to keep this flag up to date as attributes are added and removed
    from the instance's dictionary. This is consistent with current
    Python. If you add a __setattr__ method to an object after it is in
    use, that method will not behave as it would if it were available at
    "compile" time.

    The implementation of delete is analogous to the implementation
    of set.

 Paul Prescod - Not encumbered by corporate consensus
"Hardly anything more unwelcome can befall a scientific writer than 
having the foundations of his edifice shaken after the work is 
finished.  I have been placed in this position by a letter from 
Mr. Bertrand Russell..." 
 - Frege, Appendix of Basic Laws of Arithmetic (of Russell's Paradox)