32

次のことを行うためのより良い方法はありますか?

try:
    a.method1()
except AttributeError:
    try:
        a.method2()
    except AttributeError:
        try:
            a.method3()
        except AttributeError:
            raise

それはかなり厄介に見えます、そして私はむしろしたくありません:

if hasattr(a, 'method1'):
    a.method1()
else if hasattr(a, 'method2'):
    a.method2()
else if hasattr(a, 'method3'):
    a.method3()
else:
    raise AttributeError

最大の効率を維持するため。

4

6 に答える 6

25

秒をわずかに変更すると、非常に素晴らしくシンプルに見えます。2つのパフォーマンスの違いに気付くとは思えません。これは、ネストされたtry/exceptsよりも少し優れています

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

他の非常に読みやすい方法は、..

def something(a):
    try:
        return a.method1()
    except:
        pass

    try:
        return a.method2()
    except:
        pass

    try:
        return a.method3()
    except:
        pass

    raise AttributeError

長い間、関数が何をしているのかは非常に明白です.パフォーマンスは実際には問題にならないはずです (いくつかの try/except ステートメントによってスクリプトの速度が著しく低下する場合は、スクリプト構造に大きな問題がある可能性があります)。

于 2009-03-31T15:50:14.267 に答える
22

おそらく、次のようなことを試すことができます。

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

次のように呼び出します。

call_attrs(a, ['method1', 'method2', 'method3'])

これは、リストにある順序でメソッドを呼び出そうとします。引数を渡したい場合は、次のようにリストの後に渡すことができます。

call_attrs(a, ['method1', 'method2', 'method3'], arg1, arg2)
于 2009-03-31T15:19:15.543 に答える
5
method = (
        getattr(a, 'method1', None) or
        getattr(a, 'method2', None) or
        getattr(a, 'method3')
        )
method()

これはまず を探し、method1次にを探します。いずれかが見つかるとすぐに検索が停止します。メソッドが見つからない場合、最後のメソッドで例外が発生します。method2method3getattr

于 2011-11-01T18:53:37.190 に答える
4

呼び出しを関数にカプセル化するのはどうですか?

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
于 2009-03-31T15:17:52.037 に答える
3

コンパクトなソリューション:

getattr(a, 'method1',
    getattr(a, 'method2',
        getattr(a, 'method3')))()
于 2011-03-10T07:07:14.807 に答える
1

新しいスタイルのオブジェクトを使用している場合:

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

もちろん、新しいスタイルのオブジェクトを使用していない場合は、__dict__代わりに__getattribute__.

編集: このコードは非常に混乱している可能性があります。__getattribute__または__dict__が見つからない場合は、どのような種類のエラーが発生したかを大まかに推測してください。

于 2009-03-31T15:21:54.977 に答える