2017-08-17 2 views
-1

Bitte helfen Sie mir zu verstehen, warum das funktioniert. Der folgende Code listet Duplikate in einem iterierbaren Code auf. Allerdings verhält sich die Verwendung der oder Betreiber wie die sonst in einer if..else Aussage ..Ist OR und ELSE ähnlich in Liste Verständnis Aussage

j = set() 
my_list = [1, 2, 3 ,3 , 3 ,4, 4] 
j_add = j.add 
twice = set(x for x in my_list if x in j or j_add(x)) 
print list(twice) 

erwarten die Linie zu sein:

twice = set(x for x in my_list if x in j else j_add(x)) 

Gedanken oder gibt einen booleschen nicht ein Wert

+1

Technisch gesehen haben Sie kein Listenverständnis, Sie haben einen Generatorausdruck. –

+1

Nein, das 'oder' ist kein' else' Statement. Es ist Teil des Tests. Sie können den gleichen booleschen Ausdruck in jeder 'if'- oder' while'-Anweisung verwenden. 'or' ** short-circuits **, wird der rechte Ausdruck nicht ausgeführt, wenn der linke Ausdruck einen wahren Wert ergibt. –

+0

Danke..das Ziel ist nicht, Duplikate zu entfernen, sondern um sie zu erfassen. Der obige Code gibt bei der Ausführung [3, 4] zurück. –

Antwort

1

Der Operator or gibt das letzte ausgewertete Argument zurück, das ein boolescher Wert sein kann oder nicht.

Dieses Verhalten wird in der Documentation erklärt:

Beachten Sie, dass weder and noch or den Wert beschränken und geben sie zurück zum False und True, sondern das letzte Argument ausgewertet zurück. Dies ist manchmal nützlich, z. B. wenn s eine Zeichenfolge ist, die durch einen Standardwert ersetzt werden soll, wenn sie leer ist, liefert der Ausdruck s or 'foo' den gewünschten Wert.

Natürlich hilft es, sich daran zu erinnern, was als falsch interpretiert wird, und dem, was als wahr interpretiert wird:

[D] ie werden folgende Werte als falsch interpretiert: False, None, numerisch Null aller Typen und leere Strings und Container (einschließlich Strings, Tupel, Listen, Wörterbücher, Sets und frozensets). Alle anderen Werte werden als wahr interpretiert.

So in dem Ausdruck:

A = B or C 

Wie @MartijnPieters in einem Kommentar weist darauf hin, ein or Ausdruck Kurzschlüsse. Wenn das erste Argument (B in diesem Fall) als wahr interpretiert wird, muss der gesamte Ausdruck wahr sein, damit das zweite Argument (C) niemals ausgewertet wird. Daher ist das erste Argument (B) "das letzte ausgewertete Argument" und wird zurückgegeben. Wenn jedoch das erste Argument (B) als falsch interpretiert wird, muss das zweite Argument (C) noch ausgewertet werden, um die Wahrheit des Ausdrucks zu bestimmen (es findet kein Kurzschluss statt). In diesem Fall ist "das letzte ausgewertete Argument" das zweite Argument (C), das zurückgegeben wird, unabhängig davon, ob der Ausdruck wahr oder falsch ist.

Es effektiv das gleiche wie das erreicht Conditional Expression:

A = B if B else C 

jedoch Bedingte Ausdrücke wurden nur hinzugefügt, um Python in der Version 2.5, während der Booleschen Operator Verhalten von Anfang an (oder zumindest existiert für eine sehr lange Zeit). Die meisten erfahrenen Python-Programmierer erkennen und haben die Angewohnheit, A = B or C zu verwenden.Bedingte Ausdrücke sind üblicherweise für komplexere Bedingungen reserviert, die nicht mit einem einfachen or funktionieren (zum Beispiel in A = B if X else C basiert die Bedingung nicht auf der Wahrheit von B, sondern X, was alles von einem einfachen Wert bis zu einem komplexen Ausdruck sein könnte).

Allerdings müssen Sie vorsichtig sein, denn, wie JaredGoguen in seiner Antwort darauf hinweist, ändert das Ändern der or in eine else in der OP-Beispiel tatsächlich das Verhalten des Codes. Dieser Code wurde geschrieben, um von diesem spezifischen Verhalten des Operators or abhängig zu sein. Sie können nicht einfach jede Verwendung von or für die Zuweisung mit einem bedingten Ausdruck ersetzen. Ein zusätzliches Refactoring kann ebenfalls erforderlich sein.

1

Ich könnte hier ein Werturteil machen und sagen, dass dies kein guter Code ist, weil es das Kurzschlussverhalten von or verwendet, um einen Nebeneffekt zu erzeugen.

Betrachten Sie die gegebene Bedingung: if x in j or j_add(x).

Wenn x in j die or Kurzschlüsse, überspringen den j_add(x) Teil der bedingten und bewertet wie True.

Wenn x not in j, wird die Aussage j_add(x) auf seine Wahrheit überprüft. Diese Methode gibt None zurück, was falsy ist, und so or als False auswerten.

Also, die gesamte Bedingung wird das gleiche wie x in j bewerten. Jedoch hat j_add(x) den Nebeneffekt des Hinzufügens x zu j! Dieser Nebeneffekt wird ausgenutzt, um die eindeutigen Mitglieder my_list in einem schnell-und-schmutzigen Verständnis aufzunehmen.

Ändern der or zu einer noch elsej beliebig konstruieren würde, aber es wäre None, den Rückgabewert von j_add(x), zu twice unangemessen hinzuzufügen.

Verwandte Themen