2009-04-15 2 views
46

Ist es eine schlechte Übung, das folgende Format zu verwenden, wenn my_var None sein kann?Ist es sicher, sich in if-Anweisungen auf die Bedingungsevaluierungsreihenfolge zu verlassen?

if my_var and 'something' in my_var: 
    #do something 

Das Problem ist, dass 'something' in my_var eine Typeerror werfen, wenn my_var Keine ist.

Oder soll ich:

if my_var: 
    if 'something' in my_var: 
     #do something 

oder

try: 
    if 'something' in my_var: 
     #do something 
except TypeError: 
    pass 

die Frage neu zu formulieren, welche der oben genannten ist die beste Praxis in Python (falls vorhanden)?

Alternativen sind willkommen!

Antwort

64

Es ist sicher abhängig von der Reihenfolge der Bedingungen (Python reference here), speziell wegen des Problems, auf das Sie hinweisen - es ist sehr nützlich, die Auswertung kurzschließen zu können, die Probleme in einer Reihe von Bedingungen verursachen könnte.

Diese Art von Code erscheint in den meisten Sprachen auf:

IF exists(variable) AND variable.doSomething() 
    THEN ... 
+2

Wenn ich Code wie der zweite sehe, nehme ich an, der Codierer hat nicht verstanden, wie Kurzschlussauswertung funktioniert. – Dana

+1

-1: Kein Zitat aus der Dokumentation: http://docs.python.org/library/stdtypes.html#boolean-operations-and-o-not –

+0

@cfi: Da ich meine Stimme ändern kann, nachdem sich die Antwort ändert, Ich bin unklar, was das Problem ist. –

1

Es vollkommen sicher ist und ich tue es die ganze Zeit.

1

Ich würde mit dem Versuch gehen/außer, aber es hängt davon ab, was Sie über die Variable wissen.

Wenn Sie erwarten, dass die Variable die meiste Zeit existiert, dann ist ein Versuch/Ausnahme weniger Operationen. Wenn Sie die meiste Zeit erwarten, dass die Variable None ist, ist eine IF-Anweisung weniger Operationen.

+0

warum (Lesbarkeit, Leistung, etc.)? – tgray

+0

Ich aktualisierte die Antwort –

27

Ja, es ist sicher, es ist ausdrücklich und sehr deutlich in der Sprache Referenz definiert:

Der Ausdruck x and y wertet zunächst x; Wenn xfalse ist, wird der Wert zurückgegeben. Andernfalls wird y ausgewertet und der resultierende Wert zurückgegeben.

Der Ausdruck x or y wertet zuerst x aus; Wenn x wahr ist, wird der Wert zurückgegeben. Andernfalls wird y ausgewertet und der resultierende Wert zurückgegeben.

+1

Schwach: es ist nicht "sicher" - es ist absolut erforderlich, um auf die Bestellung abhängen. –

1

Es ist nicht so einfach. Als C# Geck bin ich etwas zu tun, wie sehr verwendet:

if(x != null && ! string.isnullorempty(x.Name)) 
{ 
    //do something 
} 

Die oben funktioniert gut und wird als erwartet bewertet. In VB.Net würde das folgende jedoch ein Ergebnis produzieren, das Sie nicht erwartet haben:

If Not x Is Nothing **And** Not String.IsNullOrEmpty(x.Name) Then 

    'do something 

End If 

Das obige generiert eine Ausnahme.Die korrekte Syntax sollte

sein
If Not x Is Nothing **AndAlso** Not String.IsNullOrEmpty(x.Name) Then 

    'do something 

End If 

Beachten Sie den sehr feinen Unterschied. Das hat mich ungefähr 10 Minuten verwirrt (viel zu lange) und deshalb müssen C# (und andere) Leute sehr vorsichtig sein, wenn sie in anderen Sprachen programmieren.

2

ich sein kann, ein wenig pedantisch, hier zu sein, aber ich würde sagen, die beste Antwort

if my_var is not None and 'something' in my_var: 
    #do something 

Der Unterschied ist die explizite Kontrolle für None, anstatt die implizite Konvertierung von my_var-True oder False zu sein.

Während ich in Ihrem Fall bin sicher, dass die Unterscheidung nicht wichtig ist, in dem allgemeineren Fall wäre es durchaus möglich, dass der Variable nicht None sein, sondern bewertet noch zu False, zum Beispiel eines ganzzahligen Wert von 0 oder eine leere Liste.

Also im Gegensatz zu den meisten der anderen Poster Behauptungen, dass es sicher ist, würde ich sagen, dass es sicher ist, solange Sie explizit sind. Wenn Sie nicht überzeugt sind, dann betrachten Sie diese sehr gekünstelt Klasse:

class Contrived(object): 
    def __contains__(self, s): 
     return True 
    def __nonzero__(self): 
     return False 

my_var = Contrived() 
if 'something' in my_var: 
    print "Yes the condition is true" 
if my_var and 'something' in my_var: 
    print "But this statement won't get reached." 
if my_var is not None and 'something' in my_var: 
    print "Whereas this one will." 

Ja, ich weiß, das ist kein realistisches Beispiel, aber Variationen in echtem Code passieren, vor allem, wenn None verwendet, um eine Standardfunktion Argument anzuzeigen.

+0

sicherlich, wenn Sie eine leere Liste oder einen Container haben, ist die 'in' Operation bedeutungslos. Ich denke OP hat es genau richtig. während es möglich ist, etwas aufzubauen, um seinen Standpunkt zu beweisen, glaube ich nicht, dass irgendein anständiger Code sich in den Fuß schießen sollte. – SilentGhost

+1

Ja, es ist ein erfundenes Beispiel, aber mein Hauptpunkt ist, dass es leicht ist, in die schlechte Angewohnheit zu geraten, zu sagen "if var" wenn du wirklich meinst "wenn Var nicht ist". Sobald Sie in diese Gewohnheit geraten, kann es Sie leicht beißen, besonders mit ausgefallenen Argumenten. –

+0

Ich denke, es ist ziemlich klar, dass OPs Absicht war, 'if var' zu sagen und genau das tat er. – SilentGhost

Verwandte Themen