简体   繁体   English

python 中的嵌套 try 语句?

[英]Nested try statements in python?

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.以保持最高效率。

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我真的怀疑你会注意到两者之间的任何性能差异,这比嵌套的 try/excepts 好一点

def something(a):
    for methodname in ['method1', 'method2', 'method3']:
        try:
            m = getattr(a, methodname)
        except AttributeError:
            pass
        else:
            return m()
    raise AttributeError

The 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 AttributeError

While 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)虽然很长,但很明显 function 正在做什么。性能确实不应该成为问题(如果一些 try/except 语句显着减慢了您的脚本速度,那么脚本结构可能存在更大的问题)

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 AttributeError

You 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:如果你想传递任何 arguments,你可以像这样在列表之后传递它们:

call_attrs(a, ['method1', 'method2', 'method3'], arg1, arg2)
method = (
        getattr(a, 'method1', None) or
        getattr(a, 'method2', None) or
        getattr(a, 'method3')
        )
method()

This will first look for method1 , then method2 , then method3 .这将首先查找method1 ,然后是method2 ,然后method3 The search will stop as soon as one of them is found.一旦找到其中一个,搜索将立即停止。 If none of the methods are found the last getattr will raise an exception.如果没有找到任何方法,最后一个getattr将引发异常。

How about encapsulating the calls in a function?将调用封装在 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:
        raise

A compact solution:紧凑的解决方案:

getattr(a, 'method1',
    getattr(a, 'method2',
        getattr(a, 'method3')))()

If you are using new-style object:如果您使用的是新型 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 AttributeError

Of course, if you aren't using a new-style object, you may try __dict__ instead of __getattribute__ .当然,如果您不使用新式 object,您可以尝试使用__dict__而不是__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.如果找不到__getattribute____dict__ ,请大胆猜测会引发什么样的错误。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM