Attributes PEP Enhancement

Paul Prescod paul at prescod.net
Mon Jul 24 02:00:02 EDT 2000


Okay, the strong preference of people on the list is for separate method
handlers for __set_XXX__ and __get_XXX___. I propose the following
algorithm to try and keep performance reasonable (though probably not as
good as with the single-method proposal).

When Python sees a class like this:

class Foo:
    def __set_XXX__( self ):
        pass

It would add two things to the class's dict.

__set_XXX__ = <unbound method>
XXX = <attribute handler flag object>

Now let's say you see this code:

Foo().XXX

This will find the attribute handler object. It will discard that object
immediately and *restart* its search at the beginning, now looking for
__get_XXX__.  In other words, it detects that XXX is a "special
attribute" because of an entry in the dictionary but it uses full Python
inheritance rules to find the appropriate method. In essence the
attribute handler object is *just a flag* not a useful piece of
information. The flag is important because how else would we know when
to look for a __get_XXX__ function? When we are looking up attributes
that do NOT have handlers, the performance should be identical to today.

If you do this:

foo=Foo()
foo.__dict__["XXX"]=5

...you will blow away all three attribute handlers for that attribute.
You can get them back by reassigning the attribute handler flag object
to foo.XXX.

If there is no getattr defined then it looks for a generic __getattr__
(as per usual) and otherwise raises AttributeError.

Setattr works like this: First it does a getattr to see if there is an
attribute handler object. This first getattr can be optimized away for
objects that have no attribute handlers at all. If there is no attribute
handler flag for XXX, the code continues as with today's Python.

If there is a handler flag, Python looks for a setter function. If it
finds one, it calls it. If it can't find it then we have somewhat of a
problem. We can either just allow the write using traditional Python
rules or raise an AttributeError. I think that the latter is appropriate
because remember what the former will do. It will *overwrite your
handler*. That isn't a good default action. Another possible default
action is to write to __XXX instead of XXX. 

It would be nice if foo.__dict__["XXX"] were "available" for use rather
than reserved by the mechanism but I don't see how to work that and
still get decent performance for property gets -- especially property
gets that are NOT related to the feature. Anyhow, hacking your
dictionary is ugly. Just use foo.__xxx .

-- 
 Paul Prescod - Not encumbered by corporate consensus
New from Computer Associates: "Software that can 'think', sold by 
marketers who choose not to."




More information about the Python-list mailing list