Skip to content

Instantly share code, notes, and snippets.

@uniphil
Last active December 14, 2015 22:19
Show Gist options
  • Select an option

  • Save uniphil/5158041 to your computer and use it in GitHub Desktop.

Select an option

Save uniphil/5158041 to your computer and use it in GitHub Desktop.
__getattr__ is called if __getattribute__ raises an AttributeError. Raising AttributeError in __getattr__ is a bad idea...
>>> class AttrDict(dict):
... """A class that is annoyingly difficult to get right in python."""
... def __getattr__(self, attr):
... """access items by key with dot notation"""
... try:
... return super(AttrDict, self).__getitem__(attr)
... except KeyError as e:
... raise AttributeError(e) # translate the error where applicable yay
...
>>>
>>> class Something(AttrDict):
... """Hey that attrdict thing looked neat lets build something on top"""
... @property
... def thing(self):
... # code code code...
... foo = self.something_else # pretend this error is not obvious
... # code code code...
... return foo
...
... @property
... def other_thing(self):
... # code code code...
... bar = self.thing
... # code code code...
... return bar
...
>>>
>>> my_thing = Something()
>>> print my_thing.other_thing
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 8, in __getattr__
AttributeError: 'other_thing'
>>>
>>> # uh... that's weird... lets try putting in some print debugging...
...
>>> class Something(AttrDict):
... """Hey that attrdict thing looked neat lets build something on top"""
... @property
... def thing(self):
... # code code code...
... foo = self.something_else # pretend this error is not obvious
... # code code code...
... return foo
...
... @property
... def other_thing(self):
... # code code code...
... print 'DEBUG: getting that other_thing'
... bar = self.thing
... print 'DEBUG: other thing: ', bar
... # code code code...
... return bar
...
>>>
>>> my_thing = Something()
>>> print my_thing.other_thing
DEBUG: getting that other_thing
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 8, in __getattr__
AttributeError: 'other_thing'
>>>
>>> # it was printing debugs from INSIDE other_thing, yet can't find other_thing?..
...
>>>
class AttrMesser(object):
def __getattr__(self, attr):
print("Nope! lol.")
@property
def no_just_kidding(self):
print("Think you can raise attribute errors from here?")
should_raise = self.nonexistent_attribute
@property
def no_really_now(self):
print("What about with an explicit raise?")
raise AttributeError
# I suppose this could be a tricky way to defer to some other behavior
# in __getattr__ from a property. And by tricky I mean terrible and I
# would never use your library.
blah = AttrMesser()
blah.no_just_kidding
blah.no_really_now
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment