Is there a nicer way of doing the following:
try:
a.method1()
except AttributeError:
try:
a.method2()
except AttributeError:
try:
a.method3()
except AttributeError:
raise
It looks pretty nasty and I'd rather not do:
if hasattr(a, 'method1'):
a.method1()
else if hasattr(a, 'method2'):
a.method2()
else if hasattr(a, 'method3'):
a.method3()
else:
raise AttributeError
to maintain maximum efficiency...
-
How about encapsulating the calls in a function?
def method_1_2_or_3(): try: a.method1() return except AttributeError: pass try: a.method2() return except AttributeError: pass try: a.method3() except AttributeError: raiseCawas : Why the "encapsulating" part? just the `pass` is a nice enough idea, it seems to me. -
Perhaps you could try something like this:
def call_attrs(obj, attrs_list, *args): for attr in attrs_list: if hasattr(obj, attr): bound_method = getattr(obj, attr) return bound_method(*args) raise AttributeErrorYou would call it like this:
call_attrs(a, ['method1', 'method2', 'method3'])This will try to call the methods in the order they are in in the list. If you wanted to pass any arguments, you could just pass them along after the list like so:
call_attrs(a, ['method1', 'method2', 'method3'], arg1, arg2) -
If you are using new-style object:
methods = ('method1','method2','method3') for method in methods: try: b = a.__getattribute__(method) except AttributeError: continue else: b() break else: # re-raise the AttributeError if nothing has worked raise AttributeErrorOf course, if you aren't using a new-style object, you may try
__dict__instead of__getattribute__.EDIT: This code might prove to be a screaming mess. If
__getattribute__or__dict__is not found, take a wild guess what kind of error is raised.Miles : Definitely use the getattr() function instead of the __getattribute__ method.David Berger : I can't entirely figure out the relative advantages of getattr vs __getattribute__. There exist objects for which either will raise AttributeError and the other will work. -
A slight change to the second looks pretty nice and simple. I really doubt you'll notice any performance difference between the two, and this is a bit nicer than a nested try/excepts
def something(a): for methodname in ['method1', 'method2', 'method3']: try: m = getattr(a, methodname) except AttributeError: pass else: return m() raise AttributeErrorThe other very readable way is to do..
def something(a): try: return a.method1() except: pass try: return a.method2() except: pass try: return a.method3() except: pass raise AttributeErrorWhile long, it's very obvious what the function is doing.. Performance really shouldn't be an issue (if a few try/except statements slow your script down noticeably, there is probably a bigger issue with the script structure)
Martin Vilcans : I like the second one since it's very readable and straight-forward. If performance is really an issue, the original poster is probably doing something wrong.
0 comments:
Post a Comment