Frage

Gibt es eine schönere Art und Weise des folgenden tun:

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

Es sieht ziemlich böse und ich möchte lieber nicht tun:

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

maximale Effizienz zu erhalten.

War es hilfreich?

Lösung

Vielleicht könnten Sie so etwas wie dies versuchen:

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

Sie würde es so nennen:

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

Dies wird versuchen, die Methoden in der Reihenfolge nennen sie in in der Liste enthalten sind. Wenn Sie irgendwelche Argumente zu übergeben wollte, könnte man sie gleich nach der Liste übergeben zusammen wie folgt:

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

Andere Tipps

Eine geringfügige Änderung der zweiten sieht ziemlich schön und einfach. Ich bezweifle wirklich, dass Sie jede Performance-Unterschied zwischen den beiden bemerken, und dies ist ein bisschen schöner als eine verschachtelte try / excepts

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

Die andere sehr lesbare Art und Weise ist zu tun ..

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

    try:
        return a.method2()
    except:
        pass

    try:
        return a.method3()
    except:
        pass

    raise AttributeError

Während lange, ist es sehr offensichtlich, was die Funktion tun wird .. Leistung sollte wirklich kein Problem sein (wenn ein paar Try / außer Aussagen Skript langsam merklich nach unten, gibt es wahrscheinlich ein größeres Problem mit der Skript Struktur)

method = (
        getattr(a, 'method1', None) or
        getattr(a, 'method2', None) or
        getattr(a, 'method3')
        )
method()

Dies wird zuerst sucht method1, dann method2, dann method3. Die Suche wird beendet, sobald einer von ihnen gefunden wird. Wenn keine der Methoden der letzte getattr erhöhen wird eine Ausnahme zu finden ist.

Wie wäre es, die Anrufe in einer Funktion Einkapseln?

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

Eine kompakte Lösung:

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

Wenn Sie mit neuem Stil Objekt:

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

Natürlich, wenn Sie keinen neuen Stil Objekt verwenden, können Sie __dict__ statt __getattribute__ versuchen.

EDIT: Dieser Code könnte sich ein Schreien Einander. Wenn __getattribute__ oder __dict__ nicht gefunden wird, nehmen eine wilde erraten, welche Art von Fehler ausgelöst wird.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top