Last active
December 14, 2015 22:19
-
-
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...
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| >>> 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?.. | |
| ... | |
| >>> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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