Gotcha I never ran into before
James Stroud
jstroud at mbi.ucla.edu
Thu Aug 9 20:45:38 EDT 2007
Brian Cole wrote:
> I've been programming in Python for about 6 years now. One of the
> features I adore the most is the very useful error messages and stack
> traces that make it easy to debug. However, today I ran into a
> difficult to trace bug because the stack trace was reporting the
> problem in the wrong place.
>
> class Delegator(object):
> def __init__(self, obj):
> self.obj = obj
> def __getattr__(self, attr):
> return getattr(self.obj, attr)
>
> class SpecializedDelegator(Delegator):
> def get_blah(self):
> return ["Returning Blah"].upper()
> blah = property(fget=get_blah)
>
> print SpecializedDelegator("Doesn't Matter").blah
>
> The stack trace is:
> Traceback (most recent call last):
> File "test.py", line 12, in ?
> print SpecializedDelegator("Doesn't Matter").blah
> File "test.py", line 5, in __getattr__
> return getattr(self.obj, attr)
> AttributeError: 'str' object has no attribute 'blah'
>
> Which is correct, but says nothing about the real problem inside the
> get_blah method. Is there a good reason that when a property's fget
> function throws an AttributeError that it should fall back on
> __getattr__? I would think since the attribute was explicitly defined
> as a property the property function should be allowed to fully crash
> and burn.
>
> Note: This example is broken up into two classes because that is how I
> discovered it. Since both classes were in separate files it added to
> the agony of debugging this. Luckily I was making a small incremental
> change so I could just back up and figure out what went wrong.
>
> Thanks,
> Brian
Your __getattr__ in in Delegator is circumventing the property in
SpecializedDelegator:
py> class Delegator(object):
... def __init__(self, obj):
... self.obj = obj
... def __getattr__(self, attr):
... return getattr(self.obj, attr)
...
py> class SpecializedDelegator(Delegator):
... def get_blah(self):
... return ["Returning Blah"].upper()
... blah = property(fget=get_blah)
...
py> print SpecializedDelegator("Doesn't Matter").blah
------------------------------------------------------------
Traceback (most recent call last):
File "<ipython console>", line 1, in <module>
File "<ipython console>", line 5, in __getattr__
<type 'exceptions.AttributeError'>: 'str' object has no attribute 'blah'
py> class Delegator(object):
... def __init__(self, obj):
... self.obj = obj
... def __getattr__(self, attr):
... if hasattr(self.obj, attr):
... return getattr(self.obj, attr)
... else:
... return self.__getattribute__(attr)
...
py> class SpecializedDelegator(Delegator):
... def get_blah(self):
... return ["Returning Blah"].upper()
... blah = property(fget=get_blah)
...
py> print SpecializedDelegator("Doesn't Matter").blah
------------------------------------------------------------
Traceback (most recent call last):
File "<ipython console>", line 1, in <module>
File "<ipython console>", line 8, in __getattr__
File "<ipython console>", line 3, in get_blah
<type 'exceptions.AttributeError'>: 'list' object has no attribute 'upper'
James
--
James Stroud
UCLA-DOE Institute for Genomics and Proteomics
Box 951570
Los Angeles, CA 90095
http://www.jamesstroud.com/
More information about the Python-list
mailing list