पायथन में "if somejj:" नहीं तो "if somejj == कोई नहीं:" से बेहतर क्यों है?


127

मैंने इस तरह कोड के कई उदाहरण देखे हैं:

if not someobj:
    #do something

लेकिन मैं सोच रहा हूँ कि क्यों नहीं कर रहा:

if someobj == None:
    #do something

क्या कोई अंतर है? क्या एक का दूसरे पर फायदा है?


13
आम तौर पर 'someobj कोई नहीं', 'someobj == कोई नहीं' के लिए बेहतर है
हारून मेंपा

क्या स्यूडोकोड के बारे में अगर एक्स कोई नहीं है? या X != None?
चार्ली पार्कर

यह प्रश्न दूसरों की तुलना में अधिक
क्रियाशील है

जवाबों:


187

पहले परीक्षण में, पायथन ऑब्जेक्ट को एक boolमान में बदलने की कोशिश करता है अगर यह पहले से ही एक नहीं है। मोटे तौर पर, हम ऑब्जेक्ट से पूछ रहे हैं: आप सार्थक हैं या नहीं? यह निम्नलिखित एल्गोरिथ्म का उपयोग करके किया जाता है:

  1. यदि ऑब्जेक्ट के पास एक __nonzero__विशेष विधि है (जैसा कि संख्यात्मक बिल्ट-इन intऔर float) करते हैं, तो यह इस विधि को कॉल करता है। इसे या तो एक boolमान वापस करना चाहिए जो फिर सीधे उपयोग किया जाता है, या एक intमूल्य जिसे माना जाता हैFalse शून्य के बराबर है।

  2. अन्यथा, अगर वस्तु एक है __len__विशेष विधि (के रूप में करने कंटेनर का निर्माण इन, list, dict, set, tuple, ...), यह इस प्रणाली को बुलाती है, एक कंटेनर पर विचारFalse अगर यह रिक्त है (लंबाई शून्य है)।

  3. अन्यथा, वस्तु पर विचार Trueतब तक किया जाता है जब तक कि यह Noneकिस स्थिति में है, यह माना जाता है False

दूसरे परीक्षण में, वस्तु की तुलना समानता के लिए की जाती है None। यहां, हम ऑब्जेक्ट से पूछ रहे हैं, "क्या आप इस अन्य मूल्य के बराबर हैं?" यह निम्नलिखित एल्गोरिथ्म का उपयोग करके किया जाता है:

  1. यदि ऑब्जेक्ट में एक __eq__विधि है, तो इसे कहा जाता है, और रिटर्न वैल्यू को फिर एक boolमूल्य में परिवर्तित किया जाता है और इसका परिणाम निर्धारित करने के लिए उपयोग किया जाता हैif

  2. अन्यथा, यदि वस्तु में एक __cmp__विधि है, तो उसे कहा जाता है। इस फ़ंक्शन को intदो ऑब्जेक्ट ( -1यदि self < other, 0यदि self == other, +1यदि self > other) के क्रम को इंगित करते हुए लौटना चाहिए ।

  3. अन्यथा, वस्तु की पहचान के लिए तुलना की जाती है (यानी वे उसी वस्तु के संदर्भ में हैं, जैसा कि isऑपरेटर द्वारा परीक्षण किया जा सकता है )।

isऑपरेटर का उपयोग करके एक और परीक्षण संभव है । हम वस्तु से पूछेंगे, "क्या आप यह विशेष वस्तु हैं?"

आम तौर पर, मैं गैर-संख्यात्मक मानों के साथ पहले परीक्षण का उपयोग करने की सलाह दूंगा, समानता के लिए परीक्षण का उपयोग करने के लिए जब आप एक ही प्रकृति की वस्तुओं की तुलना करना चाहते हैं (दो तार, दो नंबर, ...) और पहचान के लिए केवल जब जांच करने के लिए। प्रहरी मूल्यों का उपयोग करना ( Noneमतलब छूट के लिए सदस्य क्षेत्र के लिए आरंभीकृत नहीं, या उपयोग करते समयgetattr या __getitem__विधि)।

संक्षेप में, हमारे पास है:

>>> 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

4
हालांकि तकनीकी रूप से सही है, इस कि tuples, सूचियों, dicts, एसटीआर, unicodes, ints, तैरता है, आदि की व्याख्या नहीं करता एक है अशून्य । बिल्ट-इन प्रकार के सत्य मूल्य पर भरोसा करने के लिए कस्टम नॉनजरो विधि पर भरोसा करना बहुत अधिक सामान्य है ।
ddaa

50

ये वास्तव में दोनों खराब व्यवहार हैं। एक बार, किसी को भी गलत तरीके से और किसी के साथ गलत व्यवहार करना ठीक माना गया था। हालाँकि, पायथन 2.2 के बाद से यह सबसे अच्छी नीति नहीं है।

सबसे पहले, जब आप एक कर if xया if not xपरीक्षण की तरह, अजगर परोक्ष कन्वर्ट करने के लिए है xबूलियन करने के लिए। boolफ़ंक्शन के लिए नियम उन चीजों की एक बेड़ा का वर्णन करते हैं जो झूठी हैं; बाकी सब सच है। यदि x का मान ठीक से शुरू करने के लिए बूलियन नहीं था, तो यह निहित रूपांतरण चीजों को कहने का सबसे स्पष्ट तरीका नहीं है।

पायथन 2.2 से पहले, कोई बूल फ़ंक्शन नहीं था, इसलिए यह और भी कम स्पष्ट था।

दूसरा, आपको वास्तव में परीक्षण नहीं करना चाहिए == None। आपको उपयोग करना चाहिए is Noneऔर is not None

PEP 8, पायथन कोड के लिए स्टाइल गाइड देखें ।

- 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!

कितने एकल हैं? पांच: None, True, False, NotImplementedऔर Ellipsis। चूंकि आप वास्तव में उपयोग करने में असमर्थ हैं NotImplementedया Ellipsis, और आप कभी नहीं कहेंगे if x is True(क्योंकि बस if xबहुत स्पष्ट है), आप कभी भी परीक्षा देंगे None


3
दूसरा रूप स्पष्ट रूप से बुरा व्यवहार नहीं है। पीईपी 8 अगर दो बार एक्स का उपयोग करने की सिफारिश करता है । पहले अनुक्रमों के लिए (लेन का उपयोग करने के बजाय) और फिर ट्रू और गलत के लिए (उपयोग करने के बजाय) है। व्यावहारिक रूप से सभी पायथन कोड मैंने देखा है यदि x और नहीं तो x का उपयोग करता है।
एंट्टी रासिनें

35

क्योंकि Noneकेवल वही चीज नहीं है जो झूठी मानी जाती है।

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, (), [], {}और ""से सभी अलग हैं Noneतो अपने दो कोड स्निपेट कर रहे हैं, नहीं के बराबर।

इसके अलावा, निम्नलिखित पर विचार करें:

>>> False == 0
True
>>> False == ()
False

if object:है एक समानता की जांच। 0, (), [], None, {}, आदि कर रहे हैं एक दूसरे से सभी अलग, लेकिन वे सभी का मूल्यांकन गलत पर।

यह लघु जादू के पीछे "जादू" है जैसे:

foo = bar and spam or eggs

जिसके लिए आशुलिपि है:

if bar:
    foo = spam
else:
    foo = eggs

हालाँकि आपको वास्तव में लिखना चाहिए:

foo = spam if bar else egg

आपके अंतिम प्रश्न के बारे में, वे समकक्ष हैं।
सिल्वेन डेफ्रेसने

और दोनों गलत हैं क्योंकि "" गलत है। दूसरे को '("",) या ("s",)' 'को पढ़ना चाहिए। वैसे भी, अजगर के आधुनिक संस्करणों में एक उचित टर्नरी ऑपरेटर होता है। इस त्रुटि-प्रवण हैक को हटा दिया जाना चाहिए।
दादा

4

पीईपी 8 - पायथन कोड के लिए स्टाइल गाइड का उपयोग करने की सिफारिश की जाती है या नहीं, यदि आप बिना-नेस के परीक्षण कर रहे हैं

- Comparisons to singletons like None should always be done with
  'is' or 'is not', never the equality operators.

दूसरी ओर यदि आप नो-नेस से अधिक के लिए परीक्षण कर रहे हैं, तो आपको बूलियन ऑपरेटर का उपयोग करना चाहिए।


3

अगर आप पूछते हैं

if not spam:
    print "Sorry. No SPAM."

स्पैम का __nonzero__ विधि कहा जाता है। पायथन मैनुअल से:

__nonzero__ ( स्व ) सत्य मूल्य परीक्षण को लागू करने के लिए कहा जाता है, और अंतर्निहित ऑपरेशन बूल (); गलत या सही लौटना चाहिए, या उनके पूर्णांक समतुल्य 0 या 1. जब इस विधि को परिभाषित नहीं किया जाता है, तो __len __ () कहा जाता है, यदि यह परिभाषित किया गया है (नीचे देखें)। यदि कोई वर्ग न तो __len __ () और न ही __nonzero __ () को परिभाषित करता है, तो उसके सभी उदाहरण सही माने जाते हैं।

अगर आप पूछते हैं

if spam == None:
    print "Sorry. No SPAM here either."

__eq__ की विधि स्पैम तर्क के साथ कॉल हो जाता है कोई नहीं

अनुकूलन संभावनाओं की अधिक जानकारी के लिए https://docs.python.org/reference/datamodel.html#basic-customization पर पायथन डॉक्यूमेंटेशन पर एक नज़र डालें


2

ये दोनों तुलनाएँ अलग-अलग उद्देश्यों की पूर्ति करती हैं। किसी चीज के बूलियन मूल्य के लिए पूर्व जांच, दूसरा बिना मूल्य के पहचान के लिए चेक।


1
पूरी तरह से सही होने के लिए, दूसरा-असमानता के लिए जाँच करता है- एक मूल्य के साथ ... "someobj is none" पहचान के लिए जाँच करता है।
मैथ्यू ट्रेवर

0

एक के लिए पहला उदाहरण छोटा है और अच्छा लग रहा है। अन्य पदों के अनुसार आप जो चुनते हैं वह इस बात पर भी निर्भर करता है कि आप वास्तव में तुलना के साथ क्या करना चाहते हैं।


0

उत्तर है, यह निर्भर करता है"।

मैं पहले उदाहरण का उपयोग करता हूं अगर मैं 0, "", [] और झूठी (सूची से बाहर नहीं निकलने वाली) को इस संदर्भ में किसी के बराबर नहीं मानता हूं।


0

व्यक्तिगत रूप से, मैंने भाषाओं में एक सुसंगत दृष्टिकोण चुना: मैं if (var)केवल (या समतुल्य) केवल अगर var को बूलियन के रूप में घोषित किया जाता है (या इस तरह परिभाषित किया गया है, C में हमारे पास एक विशिष्ट प्रकार नहीं है)। मैं भी इन चर को एक के साथ उपसर्ग करता हूं b(इसलिए यह bVarवास्तव में होगा ) यह सुनिश्चित करने के लिए कि मैं गलती से यहां दूसरे प्रकार का उपयोग नहीं करूंगा।
मुझे वास्तव में बूलियन के लिए निहित कास्टिंग पसंद नहीं है, यहां तक ​​कि जब कई, जटिल नियम भी कम होते हैं।

बेशक, लोग असहमत होंगे। कुछ आगे बढ़ते हैं, मैं if (bVar == true)अपने काम में जावा कोड में देखता हूं (मेरे स्वाद के लिए बहुत बेमानी!), दूसरों को बहुत अधिक कॉम्पैक्ट सिंटैक्स पसंद है, जा रहा है while (line = getNextLine())(मेरे लिए बहुत अस्पष्ट)।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.