How to deal __getattr__

Alex Martelli aleaxit at yahoo.com
Sun Oct 17 17:13:30 CEST 2004


limodou <limodou at gmail.com> wrote:

> I resolved the problem via defining __eq__method, just like:
> 
> >>> class A:
>       def __getattr__(self, name):
>               print name
>               return None
>       def __eq__(self, obj):
>               return id(self) == id(obj)
> 
>       
> >>> a=A()
> >>> b=A()
> >>> a==b
> False
> 
> I don't know whether it's the right solution, any ideas?

I think it's a weak solution: you can now do a==b, but if you try, say,
"print a" or the implicit repr(a) the interactive interpreter does if
you just type a at the prompt, boom, your problems are there again.

I suggest:
  1. class A(object):
this makes your class newstyle and the problem goes away.  Other ways to
make classes newstyle are to assign __metaclass__=type, etc.  Newstyle
classes are recommended for new code; classic classes exists just about
only to ensure backwards compatibility for old legacy code.

  2. change __getattr__:

def __getattr__(self, name):
    print name
    if name.startswith('__') and name.endswith('__'):
        raise AttributeError, name
    return None

I don't know why you want your class's instances to pretend to have
googolplex attributes, all set to None; it seems a bad idea to me.  But
it goes from bad to terrible when the pretense affects the special names
(mostly special methods) which Python looks for in order to let you
override the semantics of many kinds of operations.  In the newstyle
object model, things are almost livable with because there is no real
dynamic lookup on the instance for the specialnames (this was discussed
in depth in a recent thread); in the classic object model it's worse.

But I would recommend you do BOTH 1 and 2.  Even in the newstyle object
module, [2] would be advisable because SOME operation, not in the bowels
of Python's own interpreter, MIGHT still be looking for a special name
as some kind of indicator that the object is a special object.

Oh btw, if you don't like the verbosity of the 2nd line in the body of
the __getattr__ I suggest, feel free to make it tighter, e.g.:
    if name[:2]+name[-2:] == '_'*4:
        raise AttributeError, name
or whatever strikes your fancy; personally, I like the clarity and
readability of the startswith and endswith methods, but I understand
that some people prefer terness instead.


Alex



More information about the Python-list mailing list