Das klappt nicht:
if cond1 && cond2:
Ich erhalte einen Fehler in der IF-Bedingung. Was mache ich falsch?
Das ist der Grund, warum Sie eine SyntaxError
ist, dass es keine &&
Operator in Python. Ebenso ||
y !
son nicht gültig Python-Operatoren.
Einige der Operatoren, die Sie vielleicht aus anderen Sprachen kennen, haben in Python einen anderen Namen. Die logischen Operatoren &&
y ||
werden eigentlich als and
y or
. Ebenso ist der logische Negationsoperator !
heißt not
.
Sie könnten also einfach schreiben:
if len(a) % 2 == 0 and len(b) % 2 == 0:
oder sogar:
if not (len(a) % 2 or len(b) % 2):
Ich habe die "Äquivalente" der Betreiber in dieser Tabelle zusammengefasst:
+------------------------------+---------------------+
| Operator (other languages) | Operator (Python) |
+==============================+=====================+
| && | and |
+------------------------------+---------------------+
| || | or |
+------------------------------+---------------------+
| ! | not |
+------------------------------+---------------------+
Siehe auch Python-Dokumentation: 6.11. Boolesche Operationen .
Neben den logischen Operatoren verfügt Python auch über bitweise/binäre Operatoren:
+--------------------+--------------------+
| Logical operator | Bitwise operator |
+====================+====================+
| and | & |
+--------------------+--------------------+
| or | | |
+--------------------+--------------------+
In Python gibt es keine bitweise Negation (nur den bitweisen Umkehroperator ~
- aber das ist no gleichbedeutend mit not
).
Siehe auch 6.6. Unäre Arithmetik und bitweise/binäre Operationen y 6.7. Binäre arithmetische Operationen .
Die logischen Operatoren haben (wie in vielen anderen Sprachen) den Vorteil, dass sie kurzgeschlossen sind. Das heißt, wenn der erste Operand bereits das Ergebnis definiert, dann wird der zweite Operator gar nicht ausgewertet.
Um dies zu zeigen, verwende ich eine Funktion, die einfach einen Wert nimmt, ihn ausgibt und wieder zurückgibt. Dies ist praktisch, um zu sehen, was tatsächlich ausgewertet wird aufgrund der Druckanweisungen ausgewertet wird:
>>> def print_and_return(value):
... print(value)
... return value
>>> res = print_and_return(False) and print_and_return(True)
False
Wie Sie sehen, wird nur eine Druckanweisung ausgeführt, so dass Python den rechten Operanden gar nicht beachtet hat.
Dies ist bei den binären Operatoren nicht der Fall. Diese werten immer beide Operanden aus:
>>> res = print_and_return(False) & print_and_return(True);
False
True
Aber wenn der erste Operand nicht ausreicht, wird natürlich der zweite Operator ausgewertet:
>>> res = print_and_return(True) and print_and_return(False);
True
False
Um dies zusammenzufassen, hier eine weitere Tabelle:
+-----------------+-------------------------+
| Expression | Right side evaluated? |
+=================+=========================+
| `True` and ... | Yes |
+-----------------+-------------------------+
| `False` and ... | No |
+-----------------+-------------------------+
| `True` or ... | No |
+-----------------+-------------------------+
| `False` or ... | Yes |
+-----------------+-------------------------+
El True
y False
darstellen, was bool(left-hand-side)
Renditen, müssen sie nicht sein True
o False
sie müssen nur zurückkehren True
o False
wenn bool
angerufen wird (1).
In Pseudo-Code(!) wird also die and
y or
Funktionen funktionieren wie folgt:
def and(expr1, expr2):
left = evaluate(expr1)
if bool(left):
return evaluate(expr2)
else:
return left
def or(expr1, expr2):
left = evaluate(expr1)
if bool(left):
return left
else:
return evaluate(expr2)
Beachten Sie, dass es sich hierbei um Pseudocode und nicht um Python-Code handelt. In Python können Sie keine Funktionen namens and
o or
denn dies sind Schlüsselwörter. Außerdem sollten Sie niemals "bewerten" oder if bool(...)
.
Diese implizite bool
Aufruf kann verwendet werden, um das Verhalten Ihrer Klassen mit and
, or
y not
.
Um zu zeigen, wie dies angepasst werden kann, verwende ich diese Klasse, die wiederum print
s etwas, um zu verfolgen, was vor sich geht:
class Test(object):
def __init__(self, value):
self.value = value
def __bool__(self):
print('__bool__ called on {!r}'.format(self))
return bool(self.value)
__nonzero__ = __bool__ # Python 2 compatibility
def __repr__(self):
return "{self.__class__.__name__}({self.value})".format(self=self)
Schauen wir uns also an, was mit dieser Klasse in Kombination mit diesen Operatoren passiert:
>>> if Test(True) and Test(False):
... pass
__bool__ called on Test(True)
__bool__ called on Test(False)
>>> if Test(False) or Test(False):
... pass
__bool__ called on Test(False)
__bool__ called on Test(False)
>>> if not Test(True):
... pass
__bool__ called on Test(True)
Wenn Sie keine __bool__
Methode prüft Python auch, ob das Objekt eine __len__
Methode und wenn sie einen Wert größer als Null zurückgibt. Dies könnte nützlich sein, wenn Sie einen Sequenzcontainer erstellen.
Siehe auch 4.1. Wahrheitswertprüfung .
Wahrscheinlich ein bisschen über den Rahmen der ursprünglichen Frage, aber für den Fall, dass Sie mit NumPy Arrays oder Unterklassen (wie Pandas Serie oder DataFrames) dann die implizite bool
aufrufen wird die gefürchtete ValueError
:
>>> import numpy as np
>>> arr = np.array([1,2,3])
>>> bool(arr)
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
>>> arr and arr
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
>>> import pandas as pd
>>> s = pd.Series([1,2,3])
>>> bool(s)
ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().
>>> s and s
ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().
In diesen Fällen können Sie die logischen und Funktion von NumPy, die eine elementweise and
(oder or
):
>>> np.logical_and(np.array([False,False,True,True]), np.array([True, False, True, False]))
array([False, False, True, False])
>>> np.logical_or(np.array([False,False,True,True]), np.array([True, False, True, False]))
array([ True, False, True, True])
Wenn Sie sich nur mit boolesche Arrays Sie könnten auch die binären Operatoren mit NumPy verwenden, diese führen elementweise (aber auch binäre) Vergleiche durch:
>>> np.array([False,False,True,True]) & np.array([True, False, True, False])
array([False, False, True, False])
>>> np.array([False,False,True,True]) | np.array([True, False, True, False])
array([ True, False, True, True])
(1)
Dass die bool
Aufruf auf die Operanden muss zurückgeben True
o False
ist nicht ganz korrekt. Es ist nur der erste Operand, der einen booleschen Wert in seinem __bool__
Methode:
class Test(object):
def __init__(self, value):
self.value = value
def __bool__(self):
return self.value
__nonzero__ = __bool__ # Python 2 compatibility
def __repr__(self):
return "{self.__class__.__name__}({self.value})".format(self=self)
>>> x = Test(10) and Test(10)
TypeError: __bool__ should return bool, returned int
>>> x1 = Test(True) and Test(10)
>>> x2 = Test(False) and Test(10)
Das liegt daran, dass and
gibt tatsächlich den ersten Operanden zurück, wenn der erste Operand den Wert False
und wenn es sich als True
dann gibt es den zweiten Operanden zurück:
>>> x1
Test(10)
>>> x2
Test(False)
Ähnliches gilt für or
sondern genau andersherum:
>>> Test(True) or Test(10)
Test(True)
>>> Test(False) or Test(10)
Test(10)
Wenn Sie sie jedoch in einem if
Anweisung der if
wird auch implizit aufrufen bool
über das Ergebnis. Diese Feinheiten sind für Sie also möglicherweise nicht relevant.
CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.