私がこれをするならば:
>>> False in [False, True]
True
これはTrue
を返します。単にFalse
がリストに含まれているからです。
しかし私がするならば:
>>> not(True) in [False, True]
False
これはFalse
を返します。 not(True)
はFalse
と同じです。
>>> not(True)
False
どうして?
not x in y
は、x not in y
として評価されます。
コードを逆アセンブルすることで、何が起こっているのかを正確に確認できます。最初のケースは期待通りに動作します。
>>> x = lambda: False in [False, True]
>>> dis.dis(x)
1 0 LOAD_GLOBAL 0 (False)
3 LOAD_GLOBAL 0 (False)
6 LOAD_GLOBAL 1 (True)
9 BUILD_LIST 2
12 COMPARE_OP 6 (in)
15 RETURN_VALUE
2番目のケースはTrue not in [False, True]
に評価されます。これは明らかにFalse
です。
>>> x = lambda: not(True) in [False, True]
>>> dis.dis(x)
1 0 LOAD_GLOBAL 0 (True)
3 LOAD_GLOBAL 1 (False)
6 LOAD_GLOBAL 0 (True)
9 BUILD_LIST 2
12 COMPARE_OP 7 (not in)
15 RETURN_VALUE
>>>
代わりに表現したいのは(not(True)) in [False, True]
で、これは予想どおりTrue
です。その理由は次のとおりです。
>>> x = lambda: (not(True)) in [False, True]
>>> dis.dis(x)
1 0 LOAD_GLOBAL 0 (True)
3 UNARY_NOT
4 LOAD_GLOBAL 1 (False)
7 LOAD_GLOBAL 0 (True)
10 BUILD_LIST 2
13 COMPARE_OP 6 (in)
16 RETURN_VALUE
演算子の優先順位in
はnot
よりも緊密にバインドされるため、式はnot((True) in [False, True])
と同等です。
これはすべて 演算子の優先順位 についてです(in
はnot
よりも強力です)。しかし、適切な場所に括弧を追加することで簡単に修正できます。
(not(True)) in [False, True] # prints true
書き込み:
not(True) in [False, True]
と同じです:
not((True) in [False, True])
これはTrue
がリストの中にあるかどうかを調べ、結果の "not"を返します。
False
はnot True in [False, True]
にあるため、True
を返す[False, True]
として評価されます。
試してみると
>>>(not(True)) in [False, True]
True
期待通りの結果が得られます。
not
の優先順位がin
より低いと述べた他の答えと並んで、実際にはあなたの文は以下と同等です。
not (True in [False, True])
ただし、自分の状態を他の状態と区別しない場合、pythonはそれを分離するために2つの役割(precedence
またはchaining
)を使用します。この場合は、pythonが優先されます。また、条件を分離したい場合は、オブジェクトや値だけでなく、すべての条件を括弧で囲む必要があります。
(not True) in [False, True]
しかし、すでに述べたように、連鎖という演算子に対するpythonによる変更がもう1つあります。
Python のドキュメントに基づく :
比較、メンバシップテスト、および同一性テストはすべて同じ優先順位を持ち、比較セクションで説明されているように左から右への連鎖機能を持っていることに注意してください。
たとえば、次の文の結果はFalse
です。
>>> True == False in [False, True]
False
なぜなら、pythonは次のように文を連鎖させるからです。
(True == False) and (False in [False, True])
これは正確にFalse and True
、つまりFalse
です。
中央のオブジェクトは、2つの操作と他のオブジェクトとの間で共有されると想定できます(この場合はFalse)。
また、メンバーシップテストやIDテストの操作(オペランドに続く)を含むすべての比較についても同じことが言えます。
in, not in, is, is not, <, <=, >, >=, !=, ==
例:
>>> 1 in [1,2] == True
False
もう一つの有名な例は数の範囲です:
7<x<20
これは以下と同じです。
7<x and x<20
他の答えのいくつかを明確にするために、括弧afterを単項演算子に追加しても優先順位は変わりません。 not(True)
は、not
をTrue
にさらに厳密にバインドさせるわけではありません。それはTrue
を囲む単なる冗長な括弧です。 (True) in [True, False]
とほとんど同じです。括弧は何もしません。バインディングをより厳密にしたい場合は、式全体を括弧で囲む必要があります。つまり、演算子とオペランドの両方、つまり(not True) in [True, False]
を意味します。
これを別の方法で見るには、
>>> -2**2
-4
**
は-
よりも緊密にバインドされます。これが、負の2の平方ではなく、2の平方の負の平方を得る理由です。
あなたが負の2の二乗を求めたとしたら?明らかに、括弧を追加します。
>>> (-2)**2
4
しかし、以下が4
を与えると期待するのは合理的ではありません。
>>> -(2)**2
-4
-(2)
は-2
と同じなので。括弧は絶対に何もしません。 not(True)
はまったく同じです。
コレクションの包含チェック操作として見てみましょう:[False, True]
はいくつかの要素を含むリストです。
True
はリストに含まれる要素なので、式True in [False, True]
はTrue
を返します。
したがって、not True in [False, True]
は、上記の式の「ブール値の反対」、not
の結果を示します(in
はnot
演算子よりも優先順位が高いため、優先順位を維持するための括弧なし)。したがって、not True
はFalse
になります。
一方、(not True) in [False, True]
はFalse in [False, True]
と等しく、これはTrue
です(False
はリストに含まれています)。
ここ は演算子の優先順位に関するドキュメントです
in binds tighter than not
そうすることは目的に役立ちます
>>> (not True) in [False, True]
True