Bunun gibi birkaç kod örneği gördüm:
if not someobj:
#do something
Ama neden yapmadığımı merak ediyorum:
if someobj == None:
#do something
Herhangi bir fark var mı? Birinin diğerine göre avantajı var mı?
X != None?
Bunun gibi birkaç kod örneği gördüm:
if not someobj:
#do something
Ama neden yapmadığımı merak ediyorum:
if someobj == None:
#do something
Herhangi bir fark var mı? Birinin diğerine göre avantajı var mı?
X != None?
Yanıtlar:
İlk testte Python, nesneyi boolzaten bir değere dönüştürmeyi dener . Kabaca, nesneye soruyoruz: anlamlı mısınız, değil misiniz? Bu, aşağıdaki algoritma kullanılarak yapılır:
Nesnenin __nonzero__özel bir yöntemi varsa (sayısal yerleşikler intve gibi float), bu yöntemi çağırır. Ya booldaha sonra doğrudan kullanılan bir intdeğer ya da Falsesıfıra eşit olduğu düşünülen bir değer döndürmelidir .
Nesne varsa Aksi takdirde, __len__özel bir yöntem (aynı do konteyner gömmeler, list, dict, set, tuple, ...), bir konteyneri düşünüldüğünde bu yöntemi çağırırFalse o (uzunluk sıfır) boşsa.
Aksi takdirde nesne, bu durumda Trueolmadığı sürece Nonedeğerlendirmeye alınır False.
İkinci testte, nesne eşitlik açısından karşılaştırılır None. Burada, "Bu diğer değere eşit misiniz?" Bu, aşağıdaki algoritma kullanılarak yapılır:
Nesnenin bir __eq__yöntemi varsa, çağrılır ve dönüş değeri daha sonra bir booldeğere dönüştürülür ve sonucun belirlenmesi için kullanılır.if .
Aksi takdirde, nesnenin bir __cmp__yöntemi varsa, çağrılır. Bu işlev int, iki nesnenin sırasını gösteren bir döndürmelidir ( -1eğer self < other, 0eğer self == other, +1eğerself > other ).
Aksi takdirde, nesne kimlik açısından karşılaştırılır (yani, isoperatör tarafından test edilebilen aynı nesneye referans olurlar ).
isOperatör kullanılarak olası başka bir test var . "Bu özel nesne misiniz?"
Genel olarak, ilk testi sayısal olmayan değerlerle kullanmanızı, aynı nitelikteki nesneleri (iki dizi, iki sayı, ...) karşılaştırmak istediğinizde eşitlik testini kullanmanızı ve yalnızca aşağıdaki durumlarda kimliği kontrol etmenizi öneririm. Sentinel değerleri kullanarak (örneğin None, bir üye alanı için başlatılmamış anlamına gelir veyagetattr veya __getitem__yöntemleri ).
Özetlemek gerekirse, elimizde:
>>> class A(object):
... def __repr__(self):
... return 'A()'
... def __nonzero__(self):
... return False
>>> class B(object):
... def __repr__(self):
... return 'B()'
... def __len__(self):
... return 0
>>> class C(object):
... def __repr__(self):
... return 'C()'
... def __cmp__(self, other):
... return 0
>>> class D(object):
... def __repr__(self):
... return 'D()'
... def __eq__(self, other):
... return True
>>> for obj in ['', (), [], {}, 0, 0., A(), B(), C(), D(), None]:
... print '%4s: bool(obj) -> %5s, obj == None -> %5s, obj is None -> %5s' % \
... (repr(obj), bool(obj), obj == None, obj is None)
'': bool(obj) -> False, obj == None -> False, obj is None -> False
(): bool(obj) -> False, obj == None -> False, obj is None -> False
[]: bool(obj) -> False, obj == None -> False, obj is None -> False
{}: bool(obj) -> False, obj == None -> False, obj is None -> False
0: bool(obj) -> False, obj == None -> False, obj is None -> False
0.0: bool(obj) -> False, obj == None -> False, obj is None -> False
A(): bool(obj) -> False, obj == None -> False, obj is None -> False
B(): bool(obj) -> False, obj == None -> False, obj is None -> False
C(): bool(obj) -> True, obj == None -> True, obj is None -> False
D(): bool(obj) -> True, obj == None -> True, obj is None -> False
None: bool(obj) -> False, obj == None -> True, obj is None -> True
Bunların ikisi de aslında kötü uygulamalardır. Bir zamanlar, Yok ve Yanlış'ı benzer olarak rastgele ele almanın uygun olduğu düşünülüyordu. Ancak, Python 2.2'den beri bu en iyi politika değildir.
İlk olarak, bir if xveya bir if not xçeşit test yaptığınızda, Python örtük xolarak boolean'a dönüştürmelidir . boolİşlevin kuralları , Yanlış olan bir yığın şeyi açıklar; diğer her şey True. X'in değeri başlangıçta doğru bir şekilde boole değilse, bu örtük dönüştürme gerçekten bir şeyleri söylemenin en net yolu değildir.
Python 2.2'den önce bool işlevi yoktu, bu yüzden daha da açık değildi.
İkincisi, gerçekten test etmemelisiniz == None. Sen kullanmalıdır is Noneve is not None.
Bkz. PEP 8, Python Kodu için Stil Kılavuzu .
- Comparisons to singletons like None should always be done with 'is' or 'is not', never the equality operators. Also, beware of writing "if x" when you really mean "if x is not None" -- e.g. when testing whether a variable or argument that defaults to None was set to some other value. The other value might have a type (such as a container) that could be false in a boolean context!
Kaç tane singleton var? Beş: None, True, False, NotImplementedve Ellipsis. Gerçekten olası olduğuna göre kullanmak NotImplementedveya Ellipsisve demezdim if x is True(çünkü if xçok nettir), sen olacak sadece hiç bir test None.
Çünkü Noneyanlış kabul edilen tek şey değil.
if not False:
print "False is false."
if not 0:
print "0 is false."
if not []:
print "An empty list is false."
if not ():
print "An empty tuple is false."
if not {}:
print "An empty dict is false."
if not "":
print "An empty string is false."
False, 0, (), [], {}Ve ""bu bakımdan farklılar Noneda iki kod parçacıkları yani, değil eşdeğeri.
Ayrıca şunları da göz önünde bulundurun:
>>> False == 0
True
>>> False == ()
False
if object:olduğu değil bir eşitlik kontrolü. 0, (), [], None, {}, Vb vardır birbirinden farklı, ama hepsi değerlendirmek False.
Bu, aşağıdaki gibi kısa süreli ifadelerin arkasındaki "sihir" dir:
foo = bar and spam or eggs
hangisinin kısaltması:
if bar:
foo = spam
else:
foo = eggs
gerçekten yazman gerekse de:
foo = spam if bar else egg
PEP 8 - Python Kodu için Stil Kılavuzu, Yokluğu test ediyorsanız eşittir veya değil kullanmanızı önerir
- Comparisons to singletons like None should always be done with 'is' or 'is not', never the equality operators.
Öte yandan, Yoktan fazlasını test ediyorsanız, boole operatörünü kullanmalısınız.
Eğer sorarsan
if not spam:
print "Sorry. No SPAM."
__nonzero__ yöntemi istenmeyen çağrılır. Python kılavuzundan:
__nonzero__ ( self ) Doğruluk değeri testini ve yerleşik bool () işlemini uygulamak için çağrılır; False veya True ya da bunların tamsayı eşdeğerleri 0 veya 1 döndürmelidir. Bu yöntem tanımlanmadığında, tanımlanmışsa __len __ () çağrılır (aşağıya bakın). Bir sınıf __len __ () veya __nonzero __ () tanımlamıyorsa, tüm örnekleri doğru olarak kabul edilir.
Eğer sorarsan
if spam == None:
print "Sorry. No SPAM here either."
__eq__ yöntemi Spam argümanı ile çağrılan Yok .
Özelleştirme olasılıkları hakkında daha fazla bilgi için, https://docs.python.org/reference/datamodel.html#basic-customization adresindeki Python belgelerine bakın.
Bu iki karşılaştırma farklı amaçlara hizmet eder. İlki, bir şeyin boole değerini kontrol eder, ikincisi ise None değerine sahip kimliği kontrol eder.
Cevap, duruma bağlı".
Bu bağlamda 0, "", [] ve False (liste ayrıntılı değil) 'nin Yok'a eşdeğer olduğunu düşünürsem ilk örneği kullanırım.
Şahsen, diller arasında tutarlı bir yaklaşım seçtim: if (var)Yalnızca var (veya eşdeğeri) boole olarak bildirilirse (veya C'de belirli bir türe sahip değilsek). Burada yanlışlıkla başka bir tür kullanmayacağımdan emin olmak için bu değişkenlerin bönüne (yani bVaraslında öyle olurdu ) bile ekledim .
Boolean'a örtük çevirmeyi gerçekten sevmiyorum, çok sayıda karmaşık kural olduğunda daha da az.
Tabii ki insanlar aynı fikirde olmayacak. Bazıları daha ileri gidiyor if (bVar == true), işimde Java kodunda görüyorum (zevkime göre çok fazla!), Diğerleri çok fazla kompakt sözdizimini seviyor, gidiyor while (line = getNextLine())(benim için çok belirsiz).