Bu, __dunder__
eşdeğer operatörleri için çoğu zaman uygun ikame olmadıklarından , yöntemlerin doğrudan kullanılmaması gerektiğine dair harika bir örnektir ; ==
Bunun yerine operatörü eşitlik karşılaştırmaları için kullanmalısınız veya bu özel durumda, kontrol ederken None
kullanın is
(daha fazla bilgi için yanıtın altına atlayın).
Yaptığın
None.__eq__('a')
Karşılaştırılan NotImplemented
türler farklı olduğu için hangi geri dönüşler . Farklı türde iki nesne gibi, bu şekilde karşılaştırılan bir örneği ele alalım 1
ve 'a'
. Yapmak (1).__eq__('a')
da doğru değil ve geri dönecek NotImplemented
. Eşitlik için bu iki değeri karşılaştırmanın doğru yolu,
1 == 'a'
Burada ne olur
- İlk önce
(1).__eq__('a')
denenir, hangi geri döner NotImplemented
. Bu, işlemin desteklenmediğini gösterir.
'a'.__eq__(1)
çağrılır, bu da aynı şeyi döndürür NotImplemented
. Yani,
- Nesneler aynı değilmiş gibi ele alınır ve
False
iade edilir.
İşte bunun nasıl gerçekleştiğini göstermek için bazı özel sınıfları kullanan küçük bir 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)
print(a == c)
print(c == a)
Elbette bu , operasyonun neden doğru döndüğünü açıklamıyor . Bunun nedeni NotImplemented
, aslında doğru bir değer olmasıdır:
bool(None.__eq__("a"))
İle aynı,
bool(NotImplemented)
Değerleri truthy kabul edilir ve falsy ne hakkında daha fazla bilgi için, dokümanlar bölümüne bakın Hakikat Değer Testi , hem de bu cevabı . Burada bunun NotImplemented
doğru olduğunu belirtmekte fayda var , ancak sınıf geri dönen bir __bool__
veya __len__
yöntemi False
veya 0
sırasıyla tanımlamış olsaydı farklı bir hikaye olurdu .
==
Operatörün işlevsel eşdeğerini istiyorsanız , şunu kullanın operator.eq
:
import operator
operator.eq(1, 'a')
Ancak, daha önce de belirtildiği gibi, kontrol ettiğiniz bu özel senaryo için şunu None
kullanın is
:
var = 'a'
var is None
var2 = None
var2 is None
Bunun işlevsel eşdeğeri kullanmaktır operator.is_
:
operator.is_(var2, None)
None
özel bir nesnedir ve herhangi bir zamanda bellekte yalnızca 1 sürüm bulunur. IOW, NoneType
sınıfın yegane singletonudur (ancak aynı nesnenin herhangi bir sayıda referansı olabilir). PEP8 kurallar bu açık hale getirmektedir:
Tekillerle karşılaştırmalar None
her zaman eşitlik operatörleriyle is
veya
is not
asla eşitlik operatörleriyle yapılmalıdır .
Özetle, singletonların gibi için None
, bir referans kontrolü is
daha uygundur, hem olsa ==
ve is
sadece iyi çalışacaktır.