I\'m writing my own container, which needs to give access to a dictionary inside by attribute calls. The typical use of the container would be like this:
dic
Your first example is perfectly fine. Even the official Python docs recommend this style known as EAFP.
Personally, I prefer to avoid nesting when it's not necessary:
def __getattribute__(self, item):
try:
return object.__getattribute__(item)
except AttributeError:
pass # fallback to dict
try:
return self.dict[item]
except KeyError:
raise AttributeError("The object doesn't have such attribute") from None
PS. has_key()
has been deprecated for a long time in Python 2. Use item in self.dict
instead.
If try-except-finally is nested inside finally block, the result from "child" finally is preserved. I have not found official expaination yet, but the following code snippet shows this behavior in Python 3.6.
def f2():
try:
a = 4
raise SyntaxError
except SyntaxError as se:
print('log SE')
raise se from None
finally:
try:
raise ValueError
except ValueError as ve:
a = 5
print('log VE')
raise ve from None
finally:
return 6
return a
In [1]: f2()
log SE
log VE
Out[2]: 6
In my opinion this would be the most Pythonic way to handle it, although and because it makes your question moot. Note that this defines__getattr__()
instead of__getattribute__()
because doing so means it only has to deal with the "special" attributes being keep in the internal dictionary.
def __getattr__(self, name):
"""only called when an attribute lookup in the usual places has failed"""
try:
return self.my_dict[name]
except KeyError:
raise AttributeError("some customized error message")
While in Java its indeed a bad practice to use Exceptions for flow control (mainly because exceptions force the jvm to gather resources (more here)), in Python you have 2 important principles: Duck Typing and EAFP. This basically means that you are encouraged to try using an object the way you think it would work, and handle when things are not like that.
In summary the only problem would be your code getting too much indented. If you feel like it, try to simplify some of the nestings like lqc suggested in the suggested answer above.
I don't think it's a matter of being pythonic or elegant. It's a matter of preventing exceptions as much as you can. Exceptions are meant to handle errors that might occur in code or events you have no control over. In this case you have full control when checking if an item is an attribute or in a dictionary, so avoid nested exceptions and stick with your second attempt.
According to the documentation, it is better to handle multiple exceptions through tuples or like this:
import sys
try:
f = open('myfile.txt')
s = f.readline()
i = int(s.strip())
except IOError as e:
print "I/O error({0}): {1}".format(e.errno, e.strerror)
except ValueError:
print "Could not convert data to an integer."
except:
print "Unexpected error:", sys.exc_info()[0]
raise