how do i create such a thing?

Alex Martelli aleaxit at yahoo.com
Mon Jan 31 08:16:38 EST 2005


Steven Bethard <steven.bethard at gmail.com> wrote:

> Of if you only want to deal with the case where the attribute doesn't
> exist, you can use getattr, which gets called when the attribute can't
> be found anywhere else:
> 
> py> class DefaultAttr(object):
> ...   def __init__(self, default):
> ...       self.default = default
> ...   def __getattr__(self, name):
> ...       return self.default
> ...   
> py> x = DefaultAttr(99)
> py> x.a
> 99
> py> x.a = 10
> py> x.a
> 10

This is a good approach, but it's fragile regarding specialnames.

>>> class DefaultAttr(object):
...   def __init__(self, default): self.default = default
...   def __getattr__(self, name): return self.default
... 
>>> import copy
>>> copy.copy(DefaultAttr(99))
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
  File "/usr/local/lib/python2.4/copy.py", line 87, in copy
    rv = reductor(2)
TypeError: 'int' object is not callable

There are many more, worse example for classic classes, but even in
newstyle classes you must consider that once in a while a system routine
will try a getattr(someinst, '__aspecialname__', None) or the like --
and your class is making its instances claim to have ANY special name
that may be introspected for in this way.  This can be a pernicious lie,
since your class in fact has no idea whatsoever what that specialname
and the corresponding value might be for.

It's HIGHLY advisable to have your __getattr__ methods raise
AttributeError for any requested name that starts and ends with double
underscores, possibly with some specific and specifically designed
exceptions.


Alex



More information about the Python-list mailing list