अगर ए बनाम अगर ए कोई नहीं है:


154

क्या में उपयोग कर सकता हूँ:

if A:

के बजाय

if A is not None:

उत्तरार्द्ध बहुत क्रियात्मक लगता है। क्या कोई अंतर है?

जवाबों:


149

बयान

if A:

कॉल करेगा A.__nonzero__()( विशेष विधि नाम प्रलेखन देखें) और उस फ़ंक्शन के रिटर्न मान का उपयोग करें। यहाँ सारांश है:

object.__nonzero__(self)

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

दूसरी ओर,

if A is not None:

केवल संदर्भ के Aसाथ तुलना Noneकरके देखें कि यह समान है या नहीं।


4
और इसलिए A is not Noneबहुत तेज है क्योंकि वहाँ काम करने के लिए बहुत कम है
जॉन ला रूय

40
@gnibbler मेरे परीक्षणों के अनुसार नहीं। if object(): pass~ 0.130 usec प्रति लूप है, जबकि if object() is not None: pass~ 0.135 usec है। वैसे भी, आपको इन दोनों के बीच चयन करने के लिए प्रदर्शन का उपयोग नहीं करना चाहिए, बल्कि उनके काम करने के तरीके में अंतर को देखना चाहिए, क्योंकि वे समान नहीं हैं ।
लॉरिट्ज वी। थुलो

1
@gnibbler धीमा if A is not Noneलगता है क्योंकि यह तुलना करने के लिए Noneएक मध्यस्थ कदम के रूप में बिलियन सिंगलटन को लोड करने की आवश्यकता है A( साथ में एक नज़र डालें dis.dis())। मुझे सही करें अगर मैं गलत हूं, लेकिन if A:अधिक कुशल लगता है, जैसे ही आप वास्तव में सत्य मूल्य का परीक्षण करना चाहते हैं न कि Noneपहचान का।
cedbeu

2
@cedbeu, मूल्य ए की मैं परीक्षण किया अब इस पर निर्भर लगता है python -m timeit -s"a=0" "if a: pass" "else: pass"तेजी से है python -m timeit -s"a=0" "if a is None: pass" "else: pass", लेकिन python -m timeit -s"a=1" "if a: pass" "else: pass"धीमी है। प्लेटफ़ॉर्म आश्रित हो सकता है, देखें कि क्या आपको वही परिणाम मिलते हैं
जॉन ला रोय

2
@cedbeu, Python3 में वे सभी बहुत तेज़ हैं, लेकिन is Noneपरीक्षण वास्तव में मेरे लिए सबसे धीमा था। Pypy में वे सभी एक ही नाप के थे :)
John La Rooy

51

PEP8 में लिखा गया है :

  • सिंगल्सटन की तुलना किसी के साथ हमेशा नहीं की जानी चाहिए जैसे कि 'है' या 'नहीं है', कभी भी समानता ऑपरेटर नहीं

    इसके अलावा, "अगर x" जब आप वास्तव में मतलब है "अगर कोई नहीं है" लिखने से सावधान रहें - उदाहरण के लिए परीक्षण करते समय कि क्या एक चर या तर्क जो कि किसी के लिए चूक नहीं है, किसी अन्य मूल्य पर सेट किया गया था। दूसरे मूल्य में एक प्रकार (जैसे कंटेनर) हो सकता है जो बूलियन संदर्भ में गलत हो सकता है!


7
मम, यह बहुत स्पष्ट नहीं है, हालांकि, और ओपी का जवाब नहीं है। पीईपी के लिए स्वचालित पुनर्निर्देशन हमेशा अच्छा जवाब नहीं होता है। बहुत बार एक एकल के साथ पहचान परीक्षा में दिलचस्पी नहीं होती है None, लेकिन सिर्फ एक सत्य मूल्य की जाँच में। इस मामले में, if A:अधिक कुशल लगता है (एक लें dis.dis(), बिलिन को लोड करने Noneऔर तुलना करने के अतिरिक्त चरण हैं if A is not None:, जबकि jump_ifअन्य मामले में केवल एक है)।
cedbeu


17

यदि उचित परिणाम नहीं मिले तो बहुत सारे कार्य वापस आ जाते हैं। उदाहरण के लिए, SQLAlchemy क्वेरी .first()विधि किसी भी परिणाम में पंक्तियाँ नहीं होने पर वापस आती है। मान लीजिए कि आप एक मान का चयन कर रहे हैं जो 0 पर वापस लौट सकता है और यह जानने की आवश्यकता है कि क्या यह वास्तव में 0 है या क्वेरी का कोई परिणाम नहीं है।

एक सामान्य मुहावरा किसी फ़ंक्शन या विधि के वैकल्पिक तर्क को किसी के डिफ़ॉल्ट मान को देना है, और फिर उस मान को देखने के लिए कोई भी परीक्षण नहीं करना है कि यह निर्दिष्ट किया गया था या नहीं। उदाहरण के लिए:

def spam(eggs=None):
    if eggs is None:
        eggs = retrievefromconfigfile()

इसकी तुलना करें:

def spam(eggs=None):
    if not eggs:
        eggs = retrievefromconfigfile()

उत्तरार्द्ध में, यदि आप फोन करते हैं spam(0)या क्या होता है spam([])? फ़ंक्शन (गलत तरीके से) का पता लगाएगा कि आपने किसी मान के लिए पास नहीं किया था eggsऔर आपके लिए डिफ़ॉल्ट मान की गणना करेगा। जो शायद आप नहीं चाहते हैं।

या "किसी दिए गए खाते के लिए लेनदेन की सूची लौटाएं" जैसी विधि की कल्पना करें। यदि खाता मौजूद नहीं है, तो यह कोई नहीं लौट सकता है। यह एक खाली सूची को वापस करने से अलग है (जिसका अर्थ होगा "यह खाता मौजूद है लेकिन लेनदेन रिकॉर्ड नहीं किया गया है)।"

अंत में, डेटाबेस सामान पर वापस जाएं। NULL और एक खाली स्ट्रिंग के बीच एक बड़ा अंतर है। एक खाली स्ट्रिंग आमतौर पर कहती है "यहाँ एक मूल्य है, और वह मूल्य कुछ भी नहीं है"। NULL का कहना है "यह मान दर्ज नहीं किया गया है।"

उन मामलों में से प्रत्येक में, आप उपयोग करना चाहते हैं if A is None। आप एक विशिष्ट मूल्य के लिए जाँच कर रहे हैं - कोई नहीं - केवल "कोई भी मूल्य जो गलत तरीके से डालने के लिए नहीं होता है"।


10

वे बहुत अलग चीजें करते हैं

नीचे दिए गए जांच करता है कि एक मान के अलावा कुछ नहीं है False, [], None, ''और 0। यह जाँच करता है मूल्य की है।

if A:

नीचे की जाँच करता है कि ए कोई नहीं की तुलना में एक अलग वस्तु है। यह संदर्भ की जांच और तुलना करता है ए और कोई नहीं (मेमोरी एड्रेस) की ।

if A is not None:

अद्यतन: आगे की व्याख्या

कई बार दोनों एक ही काम करते दिखते हैं, इसलिए बहुत से लोग इन्टरचेंज का इस्तेमाल करते हैं - यह वास्तव में बुरा विचार है। कारण दोनों एक ही परिणाम शुद्ध संयोग से कई बार है की तरह दुभाषिया / संकलक का अनुकूलन के कारण होना शामिल या कुछ और।

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

> a = 'test'
> b = 'test'
> a is b
True
> a == b
True

हालांकि अन्य चीजें वैसा ही व्यवहार नहीं करती हैं ..

> a = []
> b = []
> a is b
False
> a == b
True

दो सूचियों में स्पष्ट रूप से अपनी स्मृति है। आश्चर्यजनक रूप से टुपल्स स्ट्रिंग्स की तरह व्यवहार करते हैं।

> a = ()
> b = ()
> a is b
True
> a == b
True

संभवतः ऐसा इसलिए है क्योंकि टुपल्स को न बदलने की गारंटी दी जाती है, इस प्रकार यह एक ही मेमोरी का पुन: उपयोग करने के लिए समझ में आता है।

लब्बोलुआब यह है कि आप संयोगों पर भरोसा नहीं कर सकते । सिर्फ इसलिए कि यह एक बत्तख की तरह कुदता है इसका मतलब यह नहीं है कि यह एक बत्तख है। का उपयोग करें isऔर ==आप वास्तव में जाँच करना चाहते हैं पर निर्भर करता है। isगद्य की तरह पढ़े जाने के बाद से इन चीजों को डीबग करना मुश्किल हो सकता है कि हम अक्सर इसे खत्म कर देते हैं।


Noneएक सिंगलटन है, यह कार्यान्वयन विवरण नहीं है (इंट या स्ट्रिंग इंटर्निंग के विपरीत)। मुझे यकीन नहीं है कि मैं आपके मतलब का पालन करता हूं।
लेव लेटस्की

@LevLevitsky मेरी बात यह नहीं है कि इंटर्न करने के कारण या उससे Noneअलग व्यवहार करता है । मेरा कहना यह है कि और विभिन्न चीजों की जाँच कर रहे हैं; पहला मेमोरी एड्रेस को चेक करता है, दूसरा मेमोरी एड्रेस की सामग्री को चेक करता है। intstris==
पिथिकोस

@LevLevitsky मैंने इसे थोड़ा अधिक सुपाच्य बनाने के लिए अपना जवाब अब संपादित किया।
पिथिकोस

7

if A: A 0 है, तो गलत साबित होगा, गलत, खाली स्ट्रिंग, खाली सूची या कोई भी, जिससे अवांछित परिणाम हो सकते हैं।


1
और कई अन्य मूल्य भी, जैसे कि खाली सूची, खाली सेट, खाली ट्यूपल आदि। अनिवार्य रूप से, कुछ भी जो प्रति डॉक्सहोमथोन . org/3/library/stdtypes.html#truth-value-testing पर सत्य नहीं है
jarmod

6

अधिकांश मार्गदर्शिकाएँ मैंने देखी हैं कि आपको उपयोग करना चाहिए

यदि एक:

जब तक आपके पास अधिक विशिष्ट होने का कारण नहीं है।

कुछ मामूली अंतर हैं। ऐसे अन्य मूल्यों के अलावा कोई भी नहीं है जो झूठी लौटाता है, उदाहरण के लिए खाली सूचियाँ, या 0, इसलिए इस बारे में एक विचार करें कि यह आप वास्तव में किसके लिए परीक्षण कर रहे हैं।


5

पाइथन में कोई भी एक विशेष मूल्य नहीं है जो आमतौर पर एक असिंचित चर को नामित करता है। यह जांचने के लिए कि क्या आपके पास इस विशेष मूल्य का उपयोग नहीं है:

if A is not None

मिथ्या मूल्य पायथन में वस्तुओं का एक विशेष वर्ग है (उदाहरण के लिए झूठे, [])। यह परीक्षण करने के लिए कि क्या ए का उपयोग गलत है:

if not A

इस प्रकार, दो भाव समान नहीं हैं और आप उन्हें समानार्थक शब्द नहीं मानेंगे।


PS कोई भी गलत नहीं है, इसलिए पहली अभिव्यक्ति दूसरी का अर्थ है। लेकिन दूसरा कोई नहीं के अलावा अन्य गलत मूल्यों को शामिल करता है। अब ... यदि आप यह सुनिश्चित कर सकते हैं कि आपके पास ए में कोई नहीं होने के अलावा अन्य गलत मूल्य नहीं हो सकते हैं, तो आप पहली अभिव्यक्ति को दूसरे के साथ बदल सकते हैं।


ऐसा नहीं है कि आप गलत हैं, लेकिन यह उत्तर पहले से ही इसे कवर करता है।
मकोतो

अगर तुम बुरा न मानो तो मैं आपसे दरख्वास्त हटाने के लिए कहना चाहूंगा। मेरा उत्तर अन्य सभी के साथ समान है, शायद आपके द्वारा संदर्भित एक के साथ कम है, लेकिन एक अलग दृष्टिकोण से प्रस्तुत किया गया है, और किसी के लिए समझना आसान हो सकता है। इसके अलावा, जब मैं SO पर डाउनवोट देखता हूं तो मैं एक गलत उत्तर मान लेता हूं ... जो आप मानते हैं कि ऐसा नहीं है।
mircealungu

खैर, यह धारणा अधूरी है। यह गलत हो सकता है या बस उपयोगी नहीं है। चूंकि आपका जवाब जैसा कि मैंने कहा था कि मैं पहले से ही कवर था, मुझे यकीन नहीं है कि यह उपयोगी है।
माकोटो

4

ये संदर्भ पर निर्भर करता है।

if A:जब मैं Aसंग्रह के कुछ प्रकार होने की उम्मीद कर रहा होता हूं, तो मैं उपयोग करता हूं , और मैं केवल ब्लॉक को निष्पादित करना चाहता हूं यदि संग्रह खाली नहीं है। यह कॉलर को किसी भी अच्छी तरह से व्यवहार किए गए संग्रह को पारित करने की अनुमति देता है, खाली या नहीं, और यह वही करता है जो मुझे उम्मीद है। यह भी अनुमति देता है NoneऔरFalse ब्लॉक को निष्पादित करने की कॉलिंग कोड को दबाने के लिए, जो कभी-कभार सुविधाजनक होता है।

OTOH, अगर मुझे Aकुछ पूरी तरह से मनमानी वस्तु होने की उम्मीद है, लेकिन इसे डिफ़ॉल्ट रूप से प्राप्त किया जा सकता है None, तो मैं हमेशा उपयोग करता हूं if A is not None, क्योंकि कॉलिंग कोड एक जानबूझकर खाली संग्रह, खाली स्ट्रिंग या 0-मूल्यवान संख्यात्मक प्रकार के संदर्भ में पारित हो सकता है, या बूलियन False, या कुछ वर्ग उदाहरण जो बूलियन संदर्भ में गलत होता है।

और दूसरी तरफ, अगर मैं Aकुछ और विशिष्ट चीज़ होने की उम्मीद करता हूं (जैसे कि मैं कक्षा के तरीकों को कॉल करने जा रहा हूं), लेकिन यह Noneडिफ़ॉल्ट रूप से हो सकता था, और मैं डिफ़ॉल्ट बूलियन रूपांतरण को एक मानता हूं वर्ग की संपत्ति मुझे सभी उपवर्गों पर लागू करने में कोई आपत्ति नहीं है, तो मैं बस if A:अपनी उंगलियों को एक अतिरिक्त 12 अक्षरों को टाइप करने के भयानक बोझ को बचाने के लिए उपयोग करूंगा।


3

मैंने एक फ़ाइल बनाई, जिसे बुलाया test.pyऔर उसे दुभाषिए पर चलाया। आप यह बदल सकते हैं कि आप क्या चाहते हैं, यह सुनिश्चित करने के लिए परीक्षण करें कि पर्दे के पीछे कैसे चीजें चल रही हैं।

import dis

def func1():

    matchesIterator = None

    if matchesIterator:

        print( "On if." );

def func2():

    matchesIterator = None

    if matchesIterator is not None:

        print( "On if." );

print( "\nFunction 1" );
dis.dis(func1)

print( "\nFunction 2" );
dis.dis(func2)

यह कोडांतरक अंतर है:

स्रोत:

>>> import importlib
>>> reload( test )

Function 1
  6           0 LOAD_CONST               0 (None)
              3 STORE_FAST               0 (matchesIterator)

  8           6 LOAD_FAST                0 (matchesIterator)
              9 POP_JUMP_IF_FALSE       20

 10          12 LOAD_CONST               1 ('On if.')
             15 PRINT_ITEM
             16 PRINT_NEWLINE
             17 JUMP_FORWARD             0 (to 20)
        >>   20 LOAD_CONST               0 (None)
             23 RETURN_VALUE

Function 2
 14           0 LOAD_CONST               0 (None)
              3 STORE_FAST               0 (matchesIterator)

 16           6 LOAD_FAST                0 (matchesIterator)
              9 LOAD_CONST               0 (None)
             12 COMPARE_OP               9 (is not)
             15 POP_JUMP_IF_FALSE       26

 18          18 LOAD_CONST               1 ('On if.')
             21 PRINT_ITEM
             22 PRINT_NEWLINE
             23 JUMP_FORWARD             0 (to 26)
        >>   26 LOAD_CONST               0 (None)
             29 RETURN_VALUE
<module 'test' from 'test.py'>

2

पूर्व अधिक पाइथोनिक (बेहतर विचारधारात्मक कोड) है, लेकिन ए को गलत (कोई नहीं) होने पर ब्लॉक निष्पादित नहीं करेगा।


7
-1। जैसा @klesh उल्लेख करता है, PEP8 उपयोग करने के लिए कहता है is/is not None। PEP8 के बाद पायथन है। इसके अलावा दो परीक्षण अलग हैं
जेसीटन

1

अजगर> = 2.6,

अगर हम ऐसा लिखते हैं

if A:

के रूप में चेतावनी उत्पन्न करेगा,

FutureWarning: भविष्य के संस्करणों में इस पद्धति का व्यवहार बदल जाएगा। इसके बजाय विशिष्ट 'लेन (एलएम)' या 'एलएम कोई नहीं है' का प्रयोग करें।

तो हम उपयोग कर सकते हैं

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