IF条件付きでエラーが発生します。何が悪いのですか?
を取得する理由SyntaxError
は&&
、Pythonに演算子がないためです。同様に||
、Pythonの有効な演算子で!
はありません。
他の言語で知っている演算子の中には、Pythonでは別の名前を持つものがあります。論理演算子&&
と||
は、実際にはと呼ばand
れor
ます。同様に、論理否定演算子!
はと呼ばれnot
ます。
だからあなたはただ書くことができます:
if len(a) % 2 == 0 and len(b) % 2 == 0:
あるいは:
if not (len(a) % 2 or len(b) % 2):
いくつかの追加情報(役に立つかもしれません):
次の表に、演算子「同等」をまとめました。
+------------------------------+---------------------+
| Operator (other languages) | Operator (Python) |
+==============================+=====================+
| && | and |
+------------------------------+---------------------+
| || | or |
+------------------------------+---------------------+
| ! | not |
+------------------------------+---------------------+
Pythonのドキュメントも参照してください:6.11。ブール演算。
論理演算子の他に、Pythonにはビット単位/二項演算子もあります。
+--------------------+--------------------+
| Logical operator | Bitwise operator |
+====================+====================+
| and | & |
+--------------------+--------------------+
| or | | |
+--------------------+--------------------+
Pythonにはビット単位の否定はありません(ビット単位の逆演算子~
だけですが、これはと同等ではありませんnot
)。
6.6も参照してください。単項算術演算とビット単位/二項演算、および6.7。バイナリ算術演算。
論理演算子(他の多くの言語と同様)には、これらが短絡されるという利点があります。つまり、最初のオペランドが既に結果を定義している場合、2番目の演算子はまったく評価されません。
これを示すために、私は単に値を取り、それを出力し、再び返す関数を使用します。これは、printステートメントのために実際に何が評価されるかを確認するのに便利です。
>>> def print_and_return(value):
... print(value)
... return value
>>> res = print_and_return(False) and print_and_return(True)
False
ご覧のように、実行されるprintステートメントは1つだけなので、Pythonは実際には正しいオペランドを見さえしませんでした。
これは、2項演算子には当てはまりません。それらは常に両方のオペランドを評価します:
>>> res = print_and_return(False) & print_and_return(True);
False
True
ただし、最初のオペランドが十分でない場合は、当然、2番目の演算子が評価されます。
>>> res = print_and_return(True) and print_and_return(False);
True
False
これをまとめると、ここに別の表があります。
+-----------------+-------------------------+
| Expression | Right side evaluated? |
+=================+=========================+
| `True` and ... | Yes |
+-----------------+-------------------------+
| `False` and ... | No |
+-----------------+-------------------------+
| `True` or ... | No |
+-----------------+-------------------------+
| `False` or ... | Yes |
+-----------------+-------------------------+
True
そしてFalse
何を表すbool(left-hand-side)
リターンを、彼らがしている必要はありませんTrue
かFalse
、彼らは返す必要がありますTrue
かFalse
ときbool
(1)それらに呼ばれています。
したがって、疑似コード(!)では、and
and or
関数は次のように機能します。
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)
これはPythonコードではなく疑似コードであることに注意してください。Pythonでは、and
またはor
というキーワードが原因で、呼び出される関数を作成できません。また、「evaluate」またはを使用しないでくださいif bool(...)
。
独自のクラスの動作をカスタマイズする
この暗黙的なbool
呼び出しを使用して、クラスがand
、or
およびで動作する方法をカスタマイズできますnot
。
これをどのようにカスタマイズできるかを示すために、このクラスを使用します。これも、print
何が起こっているかを追跡するためのものです。
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)
それでは、これらの演算子と組み合わせてそのクラスで何が起こるか見てみましょう:
>>> 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)
__bool__
メソッドがない場合、Pythonはオブジェクトに__len__
メソッドがあるかどうか、およびゼロより大きい値を返すかどうかもチェックします。これは、シーケンスコンテナーを作成する場合に知っておくと便利です。
4.1も参照してください。真理値テスト。
NumPyの配列とサブクラス
おそらく元の質問の範囲を少し超えていますが、NumPy配列またはサブクラス(Pandas SeriesやDataFramesなど)を処理している場合は、暗黙的なbool
呼び出しによって恐怖が発生し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().
これらの場合、要素ごとに(または)実行するNumPyの論理関数と関数を使用できます。and
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])
ブール配列だけを扱っている場合は、NumPyで2項演算子を使用することもできます。これらは要素ごとの(ただし2進数の)比較を実行します。
>>> 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)
bool
オペランドの呼び出しは戻るTrue
必要False
があるか、完全に正しくない。これは、__bool__
メソッドでブール値を返す必要がある最初のオペランドにすぎません。
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)
これand
は、最初のオペランドが評価された場合に実際に最初のオペランドを返し、評価されたFalse
場合にTrue
2番目のオペランドを返すためです。
>>> x1
Test(10)
>>> x2
Test(False)
同様に、or
しかし逆に:
>>> Test(True) or Test(10)
Test(True)
>>> Test(False) or Test(10)
Test(10)
ただし、if
ステートメントでそれらを使用すると、if
暗黙的bool
に結果が呼び出されます。したがって、これらの細かい点はあなたには関係がないかもしれません。