कोड की इन दो पंक्तियों के बीच क्या अंतर है:
if not x == 'val':
तथा
if x != 'val':
क्या एक दूसरे से अधिक कुशल है?
क्या इसका उपयोग करना बेहतर होगा
if x == 'val':
pass
else:
कोड की इन दो पंक्तियों के बीच क्या अंतर है:
if not x == 'val':
तथा
if x != 'val':
क्या एक दूसरे से अधिक कुशल है?
क्या इसका उपयोग करना बेहतर होगा
if x == 'val':
pass
else:
जवाबों:
dis
दो संस्करणों के लिए उत्पन्न बाइटकोड को देखने के लिए उपयोग करना :
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
उत्तरार्द्ध में कम ऑपरेशन हैं, और इसलिए थोड़ा अधिक कुशल होने की संभावना है।
यह बताया गया commments में (धन्यवाद, @Quincunx ) है कि जहां आप if foo != bar
बनाम if not foo == bar
आपरेशन की संख्या बिल्कुल वैसा ही है, यह सिर्फ है कि COMPARE_OP
परिवर्तन और POP_JUMP_IF_TRUE
पर स्विच करता है 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
इस मामले में, जब तक कि प्रत्येक तुलना के लिए आवश्यक कार्य की मात्रा में अंतर नहीं होता, यह संभावना नहीं है कि आप किसी भी प्रदर्शन अंतर को देखेंगे।
हालाँकि, ध्यान दें कि दो संस्करण हमेशा तार्किक रूप से समान नहीं होंगे , क्योंकि यह प्रश्न में वस्तुओं के कार्यान्वयन के लिए __eq__
और उन पर निर्भर करेगा __ne__
। प्रति डाटा मॉडल प्रलेखन :
तुलना ऑपरेटरों के बीच कोई निहित संबंध नहीं हैं। सत्य का
x==y
अर्थ यह नहीं है किx!=y
वह असत्य है।
उदाहरण के लिए:
>>> class Dummy(object):
def __eq__(self, other):
return True
def __ne__(self, other):
return True
>>> not Dummy() == Dummy()
False
>>> Dummy() != Dummy()
True
अंत में, और शायद सबसे महत्वपूर्ण बात: सामान्य, जहां दो में कर रहे हैं तार्किक समान, x != y
की तुलना में अधिक पठनीय हैnot x == y
।
__eq__
असंगत है __ne__
वह फ्लैट-आउट टूटा हुआ है।
not x == y
एक और निर्देश है। जब मैंने कोड को एक में डाल दिया if
, तो यह पता चला कि उन दोनों के पास समान निर्देश हैं, बस एक था POP_JUMP_IF_TRUE
और दूसरे POP_JUMP_IF_FALSE
(जो कि उनके बीच एकमात्र अंतर था, एक अलग उपयोग करने के अलावा COMPARE_OP
)। जब मैंने if
एस के बिना कोड संकलित किया , तो मुझे वही मिला जो आपको मिला था।
==
और !=
परस्पर अनन्य नहीं हैं SQL जैसी कार्यान्वयन से जुड़े है null
मान। एसक्यूएल में null
वापस नहीं करता है true
करने के लिए !=
किसी अन्य मूल्य की तुलना में है, इसलिए एसक्यूएल इंटरफेस के अजगर कार्यान्वयन भी एक ही मुद्दा हो सकता है।
not ==
और !=
यह मेरे उत्तर का सबसे दिलचस्प हिस्सा लगता है! मुझे नहीं लगता कि यह उस स्थान पर है, जहां पर, क्यों और कब यह समझ में आता है - उदाहरण के लिए देखें कि पायथन के पास __ne__
सिर्फ एक ऑपरेटर की विधि क्यों है __eq__
?
@jonrsharpe का एक उत्कृष्ट विवरण है कि क्या हो रहा है। मैंने सोचा था कि मैं समय में अंतर दिखाऊंगा जब प्रत्येक 3 विकल्प 10,000,000 बार चल रहा हो (दिखाने के लिए थोड़ा अंतर के लिए पर्याप्त)।
उपयोग किया गया कोड:
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)
और cProfile प्रोफाइलर परिणाम:
इसलिए हम देख सकते हैं कि if not x == 'val':
और के बीच ~ 0.7% का एक बहुत मिनट का अंतर है if x != 'val':
। इनमें से, if x != 'val':
सबसे तेज है।
हालांकि, सबसे आश्चर्यजनक रूप से, हम यह देख सकते हैं
if x == 'val':
pass
else:
वास्तव में सबसे तेज है, और if x != 'val':
~ 0.3% से धड़कता है। यह बहुत पठनीय नहीं है, लेकिन मुझे लगता है कि यदि आप एक नगण्य प्रदर्शन सुधार चाहते हैं, तो कोई इस मार्ग से नीचे जा सकता है।
पहले एक पायथन में आवश्यक से अधिक एक ऑपरेशन को अंजाम देना होता है (इसके बजाए सिर्फ इसकी जाँच नहीं करना है कि क्या यह सच नहीं है कि यह बराबर है, इस प्रकार एक और ऑपरेशन करना है)। एक निष्पादन से अंतर बताना असंभव होगा, लेकिन अगर कई बार चलाया जाता है, तो दूसरा अधिक कुशल होगा। कुल मिलाकर मैं दूसरे का उपयोग करूंगा, लेकिन गणितीय रूप से वे समान हैं
>>> 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
यहां आप देख सकते हैं कि not x == y
एक से अधिक निर्देश हैं x != y
। इसलिए अधिकांश मामलों में प्रदर्शन अंतर बहुत कम होगा जब तक आप लाखों तुलनाएं नहीं कर रहे हैं और तब भी यह अड़चन का कारण नहीं होगा।
एक अतिरिक्त ध्यान दें, क्योंकि अन्य उत्तरों ने आपके प्रश्न का उत्तर अधिकतर सही ढंग से दिया है, यह है कि यदि कोई वर्ग केवल परिभाषित करता है __eq__()
और नहीं __ne__()
, तो आपका COMPARE_OP (!=)
भाग जाएगा __eq__()
और इसे नकार देगा। उस समय, आपका तीसरा विकल्प थोड़ा और अधिक कुशल होने की संभावना है, लेकिन केवल तभी विचार किया जाना चाहिए यदि आपने गति की आवश्यकता की है, क्योंकि इसे जल्दी से समझना मुश्किल है।
यह आपके पढ़ने के तरीके के बारे में है। not
ऑपरेटर गतिशील है, इसलिए आप इसे लागू करने में सक्षम हैं
if not x == 'val':
लेकिन !=
एक ऑपरेटर के रूप में एक बेहतर संदर्भ में पढ़ा जा सकता है जो इसके विपरीत ==
करता है।
not
ऑपरेटर गतिशील है" ?
मैं ऊपर अपनी पठनीयता टिप्पणी पर विस्तार करना चाहता हूं।
फिर, मैं पूरी तरह से अन्य (प्रदर्शन-महत्वहीन) चिंताओं को पढ़ने से सहमत हूं।
मैं जो इंगित करना चाहूंगा वह यह है कि मस्तिष्क "सकारात्मक" की तुलना में तेजी से "सकारात्मक" की व्याख्या करता है। उदाहरण के लिए, "स्टॉप" बनाम "मत जाओ" (शब्दों की संख्या में अंतर के कारण एक घटिया उदाहरण)।
इसलिए एक विकल्प दिया:
if a == b
(do this)
else
(do that)
कार्यात्मक-समतुल्य के लिए बेहतर है:
if a != b
(do that)
else
(do this)
कम पठनीयता / समझने की क्षमता अधिक कीड़े की ओर ले जाती है। शायद शुरुआती कोडिंग में नहीं, लेकिन रखरखाव के रूप में (आपके जितना स्मार्ट नहीं!) में परिवर्तन ...