How do I return None instead of raising AttributeError?
Tim Peters
tim_one at email.msn.com
Sun Sep 24 02:48:59 EDT 2000
[Scott M. Ransom]
> I want a simple class that returns None if I try and access any
> attribute that has not already been set. In other words, I want to
> return a None instead of raising an AttributeError.
It's your throat <0.7 wink>.
> Here is try number one:
>
> >>> class test1:
> ... def __getattr__(self, name):
> ... if self.__dict__.has_key(name):
> ... return self.name
> ... else:
> ... return None
> ...
> >>> a = test1()
> >>> a.b = 1.0
> >>> a.b
> 1.0
> >>> a.c
> >>> a
> Traceback (most recent call last):
> File "<stdin>", line 1, in ?
> TypeError: call of non-function (type None)
>
> This gives me (almost) the correct functionality except that I can't use
> any of the default class methods!
Well, __getattr__ can't read your mind. This does exactly what you said you
wanted: "returns None if I try and access any attribute that has not
already been set"; you didn't set "__repr__", and it returned None.
Defining __getattr__ at all announces that *you* want to be responsible for
name lookups. You want the power, you assume the responsibility.
BTW, note that __getattr__ isn't called at all for attributes that *do*
explicitly exist, so checking for self.__dict__.has_key(name) here isn't
doing anything for you (it will never be true). That is, the definition
above is the same as
def __getattr__(self, name):
return None
> The last line passes '__repr__' as name, which isn't in __dict__ and
> so a None gets returned.
>
> Try again:
>
> >>> class test2:
> ... def __getattr__(self, name):
> ... try: return self.name
> ... except AttributeError:
> ... return None
> ...
> >>> a = test2()
> >>> a.b = 1.0
> >>> a.b
> 1.0
> >>> a.c
> Segmentation fault
>
> Now a SegFault! Any idea what is happening here? (I am using Python
> 1.6 under Linux...)
It's unbounded recursion: a.c calls __getattr__ with "c", which tries
looking up self.name, which calls __getattr__ with "name", which tries
looking up self.name, which calls __getattr__ with "name", and so on, and so
on. You eventually run out of stack space and the C runtime blows up. A
lot of crap has been added to Python 2.0 to try and catch this potential
stack overflow on various platforms, and give you a message about it instead
of letting the platform dump core.
Back to your problem, like I said, Python can't read your mind. Safest
would be for you to enumerate the exact list of "default class methods" you
want to have *not* return None when they're not explicitly defined. Since
"default class method" isn't a well-defined concept in Python, nobody can do
that for you (because we can't read your mind either <wink>).
As an approximation, the names of most special methods both begin and end
with two underscores, so you can special-case that:
class test1:
def __getattr__(self, name):
if name[:2] == "__" == name[-2:]:
raise AttributeError(name)
For things like __repr__, Python first tries
instance.__getattr__("__repr__"), and if that raises an exception *then* it
backs off to the default __repr__. So this works as you hope, so far as
your examples got:
>>> a = test1()
>>> a.b = 1
>>> a.b
1
>>> a.c
>>> a
<__main__.test1 instance at 0250B56C>
>>>
But note the next one:
>>> len(a)
Traceback (innermost last):
File "<pyshell#24>", line 1, in ?
len(a)
File "C:/Python20/test.py", line 16, in __getattr__
raise AttributeError(name)
AttributeError: __len__
>>>
If you *truly* wanted every non-existent attr to return None, that last line
should blow up with some bizarre error like "call of non-function None"
instead.
Again, since you're inventing a language that's not Python in its behavior,
__getattr__ will *let* you do that, but it's up to you to define every case
the way you want it to work.
that-something-can-be-done-is-not-an-invitation-to-do-it-ly y'rs - tim
More information about the Python-list
mailing list