Bu iki kod satırı arasındaki fark nedir:
if not x == 'val':
ve
if x != 'val':
Biri diğerinden daha mı verimli?
Kullanmak daha iyi olur mu
if x == 'val':
pass
else:
Bu iki kod satırı arasındaki fark nedir:
if not x == 'val':
ve
if x != 'val':
Biri diğerinden daha mı verimli?
Kullanmak daha iyi olur mu
if x == 'val':
pass
else:
Yanıtlar:
dis
İki sürüm için oluşturulan bayt koduna bakmak için kullanma :
not ==
4 0 LOAD_FAST 0 (foo)
3 LOAD_FAST 1 (bar)
6 COMPARE_OP 2 (==)
9 UNARY_NOT
10 RETURN_VALUE
!=
4 0 LOAD_FAST 0 (foo)
3 LOAD_FAST 1 (bar)
6 COMPARE_OP 3 (!=)
9 RETURN_VALUE
İkincisinin daha az operasyonu vardır ve bu nedenle biraz daha verimli olması muhtemeldir.
Bu işaret edildi commments içinde (teşekkür, @Quincunx sahip nerede) if foo != bar
vs if not foo == bar
işlem sayısı tam olarak aynı olduğunu, sadece bu var COMPARE_OP
değişiklikler ve POP_JUMP_IF_TRUE
geçer POP_JUMP_IF_FALSE
:
not ==
:
2 0 LOAD_FAST 0 (foo)
3 LOAD_FAST 1 (bar)
6 COMPARE_OP 2 (==)
9 POP_JUMP_IF_TRUE 16
!=
2 0 LOAD_FAST 0 (foo)
3 LOAD_FAST 1 (bar)
6 COMPARE_OP 3 (!=)
9 POP_JUMP_IF_FALSE 16
Bu durumda, her karşılaştırma için gereken iş miktarında bir fark olmadıkça, herhangi bir performans farkı görmeniz pek olası değildir.
Ancak, söz konusu nesnelerin uygulamalarına ve uygulamalarına bağlı olacağından , iki sürümün her zaman mantıksal olarak aynı olmayacağını unutmayın . Başına veri modeli belgelerine :__eq__
__ne__
Karşılaştırma işleçleri arasında herhangi bir zımni ilişki yoktur. Gerçeği bunun yanlış olduğu
x==y
anlamına gelmezx!=y
.
Örneğin:
>>> class Dummy(object):
def __eq__(self, other):
return True
def __ne__(self, other):
return True
>>> not Dummy() == Dummy()
False
>>> Dummy() != Dummy()
True
Son olarak ve belki de en önemlisi: İki nereye, genel olarak şunlardır mantıksal olarak özdeş, x != y
çok daha okunabilirnot x == y
.
__eq__
tutarsız olan herhangi bir sınıf __ne__
düz olarak kırılır.
not x == y
. Kodu bir koyduğumda, if
her ikisinin de aynı sayıda talimatı olduğu ortaya çıktı, sadece biri vardı POP_JUMP_IF_TRUE
ve diğeri POP_JUMP_IF_FALSE
(farklı bir kullanım dışında, aralarındaki tek fark buydu COMPARE_OP
). Kodu if
s olmadan derlediğimde, sahip olduğun şeyi aldım.
==
ve !=
birbirini dışlamayan başka bir örnek de null
değerleri içeren SQL benzeri bir uygulamadır . SQL null
dönmez true
için !=
SQL arayüzlerinin piton uygulamaları da aynı sorunu olabilir bu yüzden başka bir değerle karşılaştırıldığında.
not ==
ve !=
cevabımın en ilginç kısmı gibi görünüyor! Ben bunun neden, neden ve ne zaman mantıklı bir yer olduğunu sanmıyorum - bkz. Örneğin Python neden __ne__
sadece bir operatör yöntemi var __eq__
?
@jonrsharpe neler olup bittiğinin mükemmel bir açıklamasına sahiptir. 3 seçeneğin her birini 10.000.000 kez çalıştırırken zaman farkını göstereceğimi düşündüm (küçük bir farkın gösterilmesi için yeterli).
Kullanılan kod:
def a(x):
if x != 'val':
pass
def b(x):
if not x == 'val':
pass
def c(x):
if x == 'val':
pass
else:
pass
x = 1
for i in range(10000000):
a(x)
b(x)
c(x)
Ve cProfile profil oluşturucu sonuçları:
Böylece if not x == 'val':
ve arasında ~% 0.7 gibi çok küçük bir fark olduğunu görebiliyoruz if x != 'val':
. Bunlardan if x != 'val':
en hızlısı.
Ancak, en şaşırtıcı şekilde,
if x == 'val':
pass
else:
aslında en hızlı ve if x != 'val':
~% 0.3 atıyor . Bu çok okunabilir değil, ama eğer ihmal edilebilir bir performans artışı isteseydiniz, biri bu rotadan aşağı gidebilir.
İlkinde Python, gerekenden daha fazla bir işlem yürütmek zorundadır (sadece eşit olmadığını kontrol etmek yerine, eşit olup olmadığını kontrol etmeli, dolayısıyla bir işlem daha yapmalıdır). Bir infazdan farkı söylemek imkansızdır, ancak birçok kez çalıştırılırsa ikincisi daha verimli olur. Genel olarak ikincisini kullanırdım, ama matematiksel olarak aynı
>>> from dis import dis
>>> dis(compile('not 10 == 20', '', 'exec'))
1 0 LOAD_CONST 0 (10)
3 LOAD_CONST 1 (20)
6 COMPARE_OP 2 (==)
9 UNARY_NOT
10 POP_TOP
11 LOAD_CONST 2 (None)
14 RETURN_VALUE
>>> dis(compile('10 != 20', '', 'exec'))
1 0 LOAD_CONST 0 (10)
3 LOAD_CONST 1 (20)
6 COMPARE_OP 3 (!=)
9 POP_TOP
10 LOAD_CONST 2 (None)
13 RETURN_VALUE
Burada not x == y
bunun bir talimat daha olduğunu görebilirsiniz x != y
. Milyonlarca karşılaştırma yapmadığınız sürece performans farkı çoğu durumda çok küçük olacaktır ve o zaman bile bu muhtemelen bir darboğazın nedeni olmayacaktır.
Diğer cevaplar çoğunlukla doğru sorunuza yanıt beri ek bir bilgi, bir sınıf yalnızca tanımlar eğer ki __eq__()
değil __ne__()
, daha sonra senin COMPARE_OP (!=)
çalışacak __eq__()
ve bunu inkâr. O zaman, üçüncü seçeneğiniz biraz daha verimli olacaktır, ancak sadece hıza İHTİYACINIZ varsa dikkate alınmalıdır, çünkü hızlı bir şekilde anlaşılması zordur.
Bu, onu okuma şeklinizle ilgilidir. not
operatörü dinamiktir, bu yüzden uygulayabilirsiniz
if not x == 'val':
Ancak !=
, bir operatörün yaptığı şeyin tersini yapan daha iyi bir bağlamda okunabilir ==
.
not
operatör dinamik" ?
Yukarıdaki okunabilirlik yorumumu genişletmek istiyorum.
Yine, diğer (performans açısından önemsiz) endişeleri geçersiz kılan okunabilirliğe tamamen katılıyorum.
Belirtmek istediğim şey, beyin "pozitif" i "negatif" den daha hızlı yorumlar. Örneğin, "dur" ve "gitme" (sözcük sayısındaki farklılık nedeniyle oldukça berbat bir örnek).
Bu yüzden bir seçenek verildi:
if a == b
(do this)
else
(do that)
işlevsel olarak eşdeğerliğe tercih edilir:
if a != b
(do that)
else
(do this)
Daha az okunabilirlik / anlaşılabilirlik daha fazla hataya neden olur. Belki ilk kodlamada değil, (sizin kadar akıllı değil!) Bakım değişir ...