[解決済み] if None.__eq__("a")` はなぜ True と評価されるように見えるのでしょうか(完全ではありませんが)?
質問
Python 3.7で以下の文を実行すると、(私のテストでは)次のように表示されます。
b
:
if None.__eq__("a"):
print("b")
しかし
None.__eq__("a")
は、次のように評価されます。
NotImplemented
.
当然です。
"a".__eq__("a")
は、次のように評価されます。
True
であり、かつ
"b".__eq__("a")
は、次のように評価されます。
False
.
私は最初、ある関数の戻り値をテストしているときにこれを発見したのですが、2番目のケースでは何も返しませんでした -- つまり、この関数は
None
.
どうなってるんだ?
解決方法は?
これは、なぜ
__dunder__
メソッドを直接使用すべきではありません。なぜなら、同等の演算子の代わりとして適切でないことが多いからです。
==
演算子の代わりに、等値比較や、この特殊なケースで
None
を使用します。
is
(詳しくは解答の一番下まで読み飛ばしてください)。
あなたが行ったのは
None.__eq__('a')
# NotImplemented
を返します。
NotImplemented
というのは、比較される型が異なるからです。別の例として、型が異なる2つのオブジェクトをこの方法で比較する場合を考えてみましょう。
1
と
'a'
. すること
(1).__eq__('a')
も正しくありません。
NotImplemented
. この 2 つの値が等しいかどうかを比較する正しい方法は、次のようになります。
1 == 'a'
# False
ここで起こることは
-
まず
(1).__eq__('a')
が試され、これはNotImplemented
. これは、その操作がサポートされていないことを示すので -
'a'.__eq__(1)
が呼び出され、これもまた同じNotImplemented
. だから -
オブジェクトは同じでないものとして扱われ
False
が返されます。
以下は、カスタムクラスを使ったちょっとしたMCVEで、これがどのように起こるかを説明しています。
class A:
def __eq__(self, other):
print('A.__eq__')
return NotImplemented
class B:
def __eq__(self, other):
print('B.__eq__')
return NotImplemented
class C:
def __eq__(self, other):
print('C.__eq__')
return True
a = A()
b = B()
c = C()
print(a == b)
# A.__eq__
# B.__eq__
# False
print(a == c)
# A.__eq__
# C.__eq__
# True
print(c == a)
# C.__eq__
# True
もちろん、それでは説明がつきません。
なぜ
が真を返します。これは
NotImplemented
は実際には真実の値である。
bool(None.__eq__("a"))
# True
と同じです。
bool(NotImplemented)
# True
どのような値が truthy と falsy とみなされるかについての詳細は、docs のセクションを参照してください。
真偽値のテスト
と同様に
この答え
. ここで注目すべきは
NotImplemented
は真実であるが、もしこのクラスが
__bool__
または
__len__
を返したメソッドです。
False
または
0
をそれぞれ指定します。
と同等の機能が必要な場合は
==
演算子を使用します。
operator.eq
:
import operator
operator.eq(1, 'a')
# False
ただし、前述したように
この特定のシナリオ
をチェックしている場合。
None
を使用します。
is
:
var = 'a'
var is None
# False
var2 = None
var2 is None
# True
これと機能的に同等なのは
operator.is_
:
operator.is_(var2, None)
# True
None
は特殊なオブジェクトであり、どの時点でもメモリ上に1バージョンしか存在しない。つまり、このオブジェクトは
NoneType
クラスへの参照を持つことができる(ただし、同じオブジェクトはいくつでも参照できる)。そのため
PEP8ガイドライン
は、これを明示します。
のようなシングルトーンとの比較
None
は、常にis
またはis not
等号演算子ではありません。
要約すると、以下のような単数形の場合
None
での参照チェックが必要です。
is
がより適切ですが、どちらも
==
と
is
は問題なく動作します。
関連
-
PicgoのイメージベッドツールをPythonで実装する
-
[解決済み】pygame.error: ビデオシステムが初期化されていない
-
[解決済み】socket.error: [Errno 48] アドレスはすでに使用中です。
-
[解決済み] builtins.TypeError: strでなければならない、bytesではない
-
[解決済み】Python elifの構文が無効です【終了しました
-
[解決済み】 'numpy.float64' オブジェクトは反復可能ではない
-
[解決済み] Windows 10でPythonを実行しようとすると "Permission Denied "と表示される。
-
[解決済み] not(True) in [False, True]」はなぜFalseを返すのですか?
-
[解決済み] (1 in [1,0] == True) はなぜ False と評価されるのでしょうか?
-
[解決済み] なぜ「a == x or y or z」は常に「真」と評価されるのですか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
Pythonコンテナのための組み込み汎用関数操作
-
python call matlab メソッドの詳細
-
Python Decorator 練習問題
-
PythonはWordの読み書きの変更操作を実装している
-
Python LeNetネットワークの説明とpytorchでの実装
-
[解決済み】Python elifの構文が無効です【終了しました
-
[解決済み] 'int'オブジェクトに'__getitem__'属性がない。
-
[解決済み】IndexError: invalid index to scalar variableを修正する方法
-
[解決済み] Pythonで2つのリストを連結する方法は?
-
[解決済み] TruthyとFalsyとは何ですか?トゥルーやファルスとどう違うの?