__getattribute__ and __slots__

Peter Otten __peter__ at web.de
Mon Apr 17 04:18:56 EDT 2006


pascal.parent at free.fr wrote:

Python has both __getattribute__() and __getattr__(). While
__getattribute__() will always be called if you ask for an attribute
__getattr__() serves only as fallback if the attribute if not found by
other means.

> I try to define a (new-style) class who:
> - have a __slots__ defined to be strict attributes,

__slots__ is a performance/memory optimization. Using __slots__ to introduce
bondage & discipline through the backdoor is against Python's spirit.

> - return None if the attribute is 'ok' but not set, or raise a 'normal'
> error if the attribute isn't in __slots__.

The approach you have chosen is a very ineffective one. Why don't you just
set the attribute to a default value in the initializer?

> This code runs, but is it the good way?

I don't think so...

> class test(object):
>      __slots__ = ['id']
>      def __getattr__(self, attr):
>              if not attr in self.__slots__: raise AttributeError
>              try:
>                      return self.attr

The line above does not do what you think it does. It just calls
test_instance.__getattr__("attr"), and since "attr" is not in __slots__ it
raises an AttributeError.

>              except:
>                      return None

You should get the same effect with

>>> class T(object):
...     __slots__ = ["id"]
...     def __getattr__(self, name):
...             if name not in self.__slots__:
...                     raise AttributeError
...             return 42 # for better visibility
...
>>> t = T()
>>> t.id
42
>>> t.whatever
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
  File "<stdin>", line 5, in __getattr__
AttributeError
>>> t.id = "something else"
>>> t.id
'something else'
>>> t.whatever = "something else"
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
AttributeError: 'T' object has no attribute 'whatever'

Peter




More information about the Python-list mailing list