New PEP: Attribute Access Handlers

Paul Prescod paul at prescod.net
Sun Jul 23 13:30:07 EDT 2000


Neel Krishnaswami wrote:
> 
> ...
> 
> I'm afraid I still don't understand. If I wanted to use separate
> accessors/mutators, what would I do with the current proposal?
> 
> An example (using separate accessors) that I'd like to see translated:
> 
> class Foo:
>    def __init__(self, x):
>        self.x = x
> 
> class LogWrites(Foo):
>    def __set_x__(self, x, val):
>        add_to_write_log()
>        self.__dict__['x'] = val
> 
> class LogReads(Foo):
>    def __get_x__(self, x):
>        add_to_read_log()
>        return self.__dict__['x']

Even under the original proposal, this wouldn't have worked.
__dict__["x"] is used by the mechanism. It can't have any value other
than the attribute access handler object if you want things to work.
self.x is reserved for the attribute access handler object. I would
expect this:

>>> print LogReads().x
<attribute access handler>

Here's how I would rewrite your code:

class Foo:
    def __init__(self, x):
       self.__x = x        
    
class LogWrites(Foo):
    def __attr_x__(self, op, val):
        if op=="set":
            self.__x=val
        else:
            raise TypeError

class LogReads(Foo):
    def __attr_x__(self, op, val):
        if op=="get":
            return self.__x
        else:
            raise TypeError

Note that LogReads().x is unwriteable even from the base class. Python
doesn't really differentiate between accesses from within the class and
from outside. Even under the "one method per operation" proposal I think
that you would have this problem. This is also the same as the current
behavior with hand-written handlers using __setattr__.

Python 1.6a2 (#0, Apr  6 2000, 11:45:12) [MSC 32 bit (Intel)] on win32
Copyright 1991-1995 Stichting Mathematisch Centrum, Amsterdam
>>> class Foo:
...     def __init__( self, x ):
...         self.x=x
...
>>> class Bar( Foo ):
...     def __setattr__( self, attr, val ):
...         if attr=="x":
...             raise TypeError, "Not writable"
...         else:
...             self.__dict__[attr]=val
...
>>> Bar(5)
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
  File "<stdin>", line 3, in __init__
  File "<stdin>", line 4, in __setattr__
TypeError: Not writable

If a class designer wants to allow sub-classes to make attributes
unreadable or unwritable, it should use __dict__["foo"] syntax rather
than attribute access syntax to read and write them.

In general, it can be painful to try and override a base class along a
"vector" that was not specifically planned by the base class designer.

-- 
 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