पायथन में अशक्त वस्तु?


जवाबों:


1626

पायथन में, 'नल' ऑब्जेक्ट सिंगलटन है None

"Noneness" के लिए चीजों की जांच करने का सबसे अच्छा तरीका पहचानकर्ता का उपयोग करना है is:

if foo is None:
    ...

125
और चुनने के लिए कारण egg is Noneसे अधिक egg == None: उत्तरार्द्ध अतिभारित किया जा सकता है, और जब कोई नहीं के साथ मान्य वस्तु की तुलना तोड़ने की संभावना है (यह कैसे लागू हो जाता है पर निर्भर करता है, लेकिन आप हर किसी के खाते में कोई भी साथ comparisions लेने के लिए की उम्मीद नहीं है, है न?) , जबकि isहमेशा एक ही काम करता है।

94
अजगर डिजाइनरों ने सिर्फ "अशक्त" क्यों नहीं चुना। बस आपको अलग होना है न! ;)
विदर

35
@ विदर 'कोई नहीं' किसी वस्तु की कमी नहीं है (जैसा कि 'अशक्त', एक शून्य संदर्भ है), यह एक वास्तविक वस्तु है। आपको कभी भी एक ऐसी वस्तु नहीं मिलेगी जो किसी वस्तु के लिए गुजरती हो, जो 'नॉटआउट' के अलावा किसी अन्य प्रकार का हो। यह भी एक भाषा की अवधारणा नहीं है .. यह पायथन भाषा में निर्मित नहीं है, यह पायथन के मानक पुस्तकालय का हिस्सा है। कोई नहीं! == (अहम) नल
रुशियो

11
@ n-0101 यह कोई उद्देश्य नहीं होगा; जैसा कि संकेत की कोई अवधारणा नहीं है। यदि आप ctypes लाइब्रेरी का उपयोग कर रहे हैं, तो कोई भी पता शून्य के समानार्थक शब्द के रूप में उपयोग नहीं किया जाएगा, लेकिन अभी भी 'शून्य संदर्भ' की कोई भाषा अवधारणा नहीं है। पायथन में, आपने हमेशा किसी प्रकार की वस्तु का संदर्भ दिया, भले ही वह वस्तु कोई भी क्यों न हो। मुझे संदेह है कि इससे भाषा सरल हो जाती है।
रशियो

5
महान प्रस्तुति dollar बिलियन डॉलर की गलती ’को स्पष्ट करती है जो अशक्त रेफरी है: infoq.com/pretations/… । अशक्त के बजाय अन्य विकल्प विकल्प या शायद (कस्टम) प्रकार हैं।
माइकल ट्रू 23

133

None, पायथन का अशक्त?

nullइसके बजाय पाइथन में कोई नहीं है None। जैसा कि पहले से ही परीक्षण का सबसे सटीक तरीका बताया गया है Noneकि मूल्य के रूप में कुछ दिया गया है, isपहचान ऑपरेटर का उपयोग करना है, जो परीक्षण करता है कि दो चर एक ही वस्तु को संदर्भित करते हैं।

>>> foo is None
True
>>> foo = 'bar' 
>>> foo is None
False

मूल बातें

वहाँ है और केवल एक ही हो सकता है None

Noneवर्ग का एकमात्र उदाहरण है NoneTypeऔर उस वर्ग को तत्काल करने का कोई भी प्रयास उसी वस्तु को लौटा देगा, जो एकल बनाता Noneहै। पायथन में नए लोग अक्सर त्रुटि संदेश देखते हैं जो उल्लेख करते हैं NoneTypeऔर आश्चर्य करते हैं कि यह क्या है। यह मेरी निजी राय है कि ये संदेश केवल Noneनाम से उल्लेख कर सकते हैं क्योंकि, जैसा कि हम जल्द ही देखेंगे, Noneअस्पष्टता के लिए बहुत कम जगह छोड़ता है। इसलिए यदि आप कुछ TypeErrorसंदेश देखते हैं जो NoneTypeऐसा नहीं कर सकते हैं या ऐसा नहीं कर सकते हैं, तो बस यह जान लें कि यह केवल एक है Noneजो इस तरह से उपयोग किया जा रहा था कि यह नहीं हो सकता।

इसके अलावा, Noneएक अंतर्निहित स्थिरांक है, जैसे ही आप पायथन शुरू करते हैं यह हर जगह से उपयोग करने के लिए उपलब्ध है, चाहे वह मॉड्यूल, वर्ग या फ़ंक्शन में हो। NoneTypeइसके विपरीत नहीं है, आपको Noneइसकी कक्षा के लिए क्वेरी करके पहले इसका संदर्भ प्राप्त करना होगा ।

>>> NoneType
NameError: name 'NoneType' is not defined
>>> type(None)
NoneType

आप Noneपायथन के पहचान समारोह के साथ अद्वितीयता की जांच कर सकते हैं id()। यह किसी ऑब्जेक्ट को निर्दिष्ट अद्वितीय संख्या देता है, प्रत्येक ऑब्जेक्ट में एक होता है। यदि दो चर की आईडी समान है, तो वे वास्तव में एक ही वस्तु की ओर इशारा करते हैं।

>>> NoneType = type(None)
>>> id(None)
10748000
>>> my_none = NoneType()
>>> id(my_none)
10748000
>>> another_none = NoneType()
>>> id(another_none)
10748000
>>> def function_that_does_nothing(): pass
>>> return_value = function_that_does_nothing()
>>> id(return_value)
10748000

None ओवरराइट नहीं किया जा सकता है

पायथन के बहुत पुराने संस्करण में (2.4 से पहले) यह फिर से असाइन करना संभव था None, लेकिन अब नहीं। एक वर्ग विशेषता के रूप में या एक समारोह के दायरे में भी नहीं।

# In Python 2.7
>>> class SomeClass(object):
...     def my_fnc(self):
...             self.None = 'foo'
SyntaxError: cannot assign to None
>>> def my_fnc():
        None = 'foo'
SyntaxError: cannot assign to None

# In Python 3.5
>>> class SomeClass:
...     def my_fnc(self):
...             self.None = 'foo'
SyntaxError: invalid syntax
>>> def my_fnc():
        None = 'foo'
SyntaxError: cannot assign to keyword

इसलिए यह मानना ​​सुरक्षित है कि सभी Noneसंदर्भ समान हैं। कोई "कस्टम" नहीं है None

ऑपरेटर के Noneउपयोग के लिए परीक्षण करनाis

जब कोड लिखना आपको इस तरह से Noneness के लिए परीक्षण करने के लिए परीक्षा दे सकता है :

if value==None:
    pass

या इस तरह झूठ का परीक्षण करना

if not value:
    pass

आपको निहितार्थ को समझने की आवश्यकता है और स्पष्ट होने के लिए अक्सर एक अच्छा विचार क्यों है।

केस 1: यदि कोई मान है तो परीक्षण None

यह क्यों

value is None

बजाय

value==None

पहला इसके बराबर है:

id(value)==id(None)

जबकि अभिव्यक्ति value==Noneवास्तव में इस तरह से लागू होती है

value.__eq__(None)

यदि मूल्य वास्तव में है, Noneतो आपको वह मिलेगा जो आपने अपेक्षित किया था।

>>> nothing = function_that_does_nothing()
>>> nothing.__eq__(None)
True

अधिकांश सामान्य मामलों में परिणाम समान होगा, लेकिन __eq__()विधि एक दरवाजा खोलती है जो सटीकता की किसी भी गारंटी से बचती है, क्योंकि विशेष व्यवहार प्रदान करने के लिए इसे कक्षा में ओवरराइड किया जा सकता है।

इस वर्ग पर विचार करें।

>>> class Empty(object):
...     def __eq__(self, other):
...         return not other

तो आप इस पर कोशिश करते हैं Noneऔर यह काम करता है

>>> empty = Empty()
>>> empty==None
True

लेकिन फिर यह खाली स्ट्रिंग पर भी काम करता है

>>> empty==''
True

और फिर भी

>>> ''==None
False
>>> empty is None
False

केस 2: Noneबूलियन के रूप में उपयोग करना

निम्नलिखित दो परीक्षण

if value:
    # do something

if not value:
    # do something

वास्तव में के रूप में मूल्यांकन कर रहे हैं

if bool(value):
    # do something

if not bool(value):
    # do something

Noneएक "गलत" है, जिसका अर्थ है कि अगर एक बूलियन को डाली जाती है तो यह वापस आ जाएगी Falseऔर यदि notइसे लागू किया जाता है तो यह वापस आ जाएगी True। ध्यान दें कि यह एक अद्वितीय संपत्ति नहीं है NoneFalseखुद के अलावा , संपत्ति को खाली सूचियों, टुपल्स, सेट्स, डीकट्स, स्ट्रिंग्स के साथ-साथ 0 से साझा किया जाता है, और कक्षाओं से सभी ऑब्जेक्ट्स जो __bool__()लौटने के लिए जादू की विधि को लागू करते हैं False

>>> bool(None)
False
>>> not None
True

>>> bool([])
False
>>> not []
True

>>> class MyFalsey(object):
...     def __bool__(self):
...         return False
>>> f = MyFalsey()
>>> bool(f)
False
>>> not f
True

इसलिए जब निम्नलिखित तरीकों से चर का परीक्षण करें, तो इस बात से अवगत रहें कि आप क्या कर रहे हैं या परीक्षण से बाहर कर रहे हैं:

def some_function(value=None):
    if not value:
        value = init_value()

उपरोक्त में, क्या आपने init_value()तब कॉल करने का मतलब है जब मूल्य विशेष रूप से सेट Noneकिया गया है , या क्या आपका मतलब है कि मूल्य सेट करने के लिए 0, या खाली स्ट्रिंग, या एक खाली सूची को भी आरंभीकरण को ट्रिगर करना चाहिए। जैसा मैंने कहा, मन हो। जैसा कि अक्सर स्पष्ट रूप से पायथन में मामला निहित से बेहतर है

None प्रयोग में

None सिग्नल मूल्य के रूप में उपयोग किया जाता है

Noneपायथन में एक विशेष दर्जा है। यह एक पसंदीदा आधारभूत मूल्य है क्योंकि कई एल्गोरिदम इसे एक असाधारण मूल्य के रूप में मानते हैं। ऐसे परिदृश्यों में यह एक ध्वज के रूप में इस्तेमाल किया जा सकता है यह संकेत देने के लिए कि किसी स्थिति के लिए कुछ विशेष हैंडलिंग (जैसे डिफ़ॉल्ट मान की सेटिंग) की आवश्यकता होती है।

आप Noneकिसी फ़ंक्शन के कीवर्ड तर्क को असाइन कर सकते हैं और फिर इसके लिए स्पष्ट रूप से परीक्षण कर सकते हैं।

def my_function(value, param=None):
    if param is None:
        # do something outrageous!

जब आप किसी वस्तु की विशेषता प्राप्त करने की कोशिश कर रहे हों और तब कुछ विशेष करने से पहले स्पष्ट रूप से उसके लिए परीक्षण कर सकें तो आप इसे डिफ़ॉल्ट के रूप में वापस कर सकते हैं।

value = getattr(some_obj, 'some_attribute', None)
if value is None:
    # do something spectacular!

डिफ़ॉल्ट रूप से एक शब्दकोश की get()विधि Noneएक गैर-मौजूदा कुंजी तक पहुंचने की कोशिश करते समय वापस आती है :

>>> some_dict = {}
>>> value = some_dict.get('foo')
>>> value is None
True

यदि आप सबस्क्रिप्ट नोटेशन का उपयोग करके इसे एक्सेस करने का प्रयास करते हैं तो KeyErrorउठाया जाएगा

>>> value = some_dict['foo']
KeyError: 'foo'

इसी तरह यदि आप किसी गैर-मौजूदा आइटम को पॉप करने का प्रयास करते हैं

>>> value = some_dict.pop('foo')
KeyError: 'foo'

जिसे आप आमतौर पर तयशुदा मान के साथ दबा सकते हैं None

value = some_dict.pop('foo', None)
if value is None:
    # booom!

None ध्वज और मान्य मान दोनों के रूप में उपयोग किया जाता है

उपर्युक्त वर्णित उपयोग Noneतब लागू होता है जब इसे एक वैध मूल्य नहीं माना जाता है, लेकिन कुछ विशेष करने के लिए एक संकेत की तरह। हालाँकि ऐसी स्थितियाँ हैं जहाँ यह कभी-कभी यह जानना मायने रखता है कि कहाँ से Noneआया है क्योंकि भले ही इसका उपयोग सिग्नल के रूप में किया जाता हो, यह डेटा का हिस्सा भी हो सकता है।

जब आप इसकी विशेषता के लिए किसी ऑब्जेक्ट को getattr(some_obj, 'attribute_name', None)वापस पाने के साथ क्वेरी करते हैं, तो आपको Noneयह नहीं बताता है कि जिस विशेषता को आप एक्सेस करने का प्रयास कर रहे हैं, वह सेट है Noneया यदि यह ऑब्जेक्ट से पूरी तरह अनुपस्थित है। समान स्थिति जब एक शब्दकोश से एक कुंजी का उपयोग some_dict.get('some_key')करते हैं , तो आप नहीं जानते कि some_dict['some_key']क्या गायब है या यदि यह अभी निर्धारित है None। यदि आपको उस जानकारी की आवश्यकता है, तो इसे संभालने का सामान्य तरीका सीधे एक try/exceptनिर्माण के भीतर से विशेषता या कुंजी तक पहुंचने का प्रयास करना है :

try:
    # equivalent to getattr() without specifying a default
    # value = getattr(some_obj, 'some_attribute')
    value = some_obj.some_attribute
    # now you handle `None` the data here
    if value is None:
        # do something here because the attribute was set to None
except AttributeError:
    # we're now hanling the exceptional situation from here.
    # We could assign None as a default value if required.
    value = None 
    # In addition, since we now know that some_obj doesn't have the
    # attribute 'some_attribute' we could do something about that.
    log_something(some_obj)

इसी तरह तानाशाह के साथ:

try:
    value = some_dict['some_key']
    if value is None:
        # do something here because 'some_key' is set to None
except KeyError:
    # set a default 
    value = None
    # and do something because 'some_key' was missing
    # from the dict.
    log_something(some_dict)

उपरोक्त दो उदाहरण बताते हैं कि वस्तु और शब्दकोश मामलों को कैसे संभालना है, कार्यों के बारे में क्या है? एक ही बात है, लेकिन हम उस छोर तक डबल तारांकन खोजशब्द तर्क का उपयोग करते हैं:

def my_function(**kwargs):
    try:
        value = kwargs['some_key'] 
        if value is None:
            # do something because 'some_key' is explicitly 
            # set to None
    except KeyError:
        # we assign the default
        value = None
        # and since it's not coming from the caller.
        log_something('did not receive "some_key"')

None केवल एक वैध मूल्य के रूप में उपयोग किया जाता है

यदि आप पाते हैं कि आपका कोड झंडे और डेटा के try/exceptबीच अंतर करने के लिए बस उपरोक्त पैटर्न से भरा हुआ है , तो बस एक और परीक्षण मान का उपयोग करें। एक ऐसा पैटर्न है जहां एक मान जो मान्य मानों के सेट के बाहर आता है, उसे डेटा संरचना में डेटा के हिस्से के रूप में डाला जाता है और इसका उपयोग विशेष परिस्थितियों (जैसे सीमाओं, राज्य, आदि) को नियंत्रित और परीक्षण करने के लिए किया जाता है। इस तरह के मूल्य को एक प्रहरी कहा जाता है और इसका उपयोग सिग्नल के रूप में जिस तरह से किया जाता है उसका उपयोग किया जा सकता है। यह पायथन में एक प्रहरी बनाने के लिए तुच्छ है।NoneNoneNone

undefined = object()

undefinedऊपर दी गई वस्तु अद्वितीय है और ऐसा कुछ भी नहीं करती है जो किसी कार्यक्रम के लिए रुचि का हो, यह इस प्रकार Noneएक ध्वज के रूप में एक उत्कृष्ट प्रतिस्थापन है । कुछ कैविएट लागू होते हैं, कोड के बाद इसके बारे में अधिक।

फ़ंक्शन के साथ

def my_function(value, param1=undefined, param2=undefined):
    if param1 is undefined:
        # we know nothing was passed to it, not even None
        log_something('param1 was missing')
        param1 = None


    if param2 is undefined:
        # we got nothing here either
        log_something('param2 was missing')
        param2 = None

हुकुम के साथ

value = some_dict.get('some_key', undefined)
if value is None:
    log_something("'some_key' was set to None")

if value is undefined:
    # we know that the dict didn't have 'some_key'
    log_something("'some_key' was not set at all")
    value = None

किसी वस्तु के साथ

value = getattr(obj, 'some_attribute', undefined) 
if value is None:
    log_something("'obj.some_attribute' was set to None")
if value is undefined:
    # we know that there's no obj.some_attribute
    log_something("no 'some_attribute' set on obj")
    value = None

जैसा कि मैंने पहले उल्लेख किया है कि प्रहरी प्रहरी कुछ कैविएट के साथ आते हैं। पहले, वे जैसे कीवर्ड नहीं हैं None, इसलिए अजगर उनकी रक्षा नहीं करता है। आप undefinedकिसी भी समय, अपने मॉड्यूल में कहीं भी इसे परिभाषित कर सकते हैं, इसलिए सावधान रहें कि आप उन्हें कैसे उजागर और उपयोग करते हैं। अगला, उदाहरण द्वारा दिया गया object()एक सिंगलटन नहीं है, यदि आप उस कॉल को 10 बार करते हैं तो आपको 10 अलग-अलग ऑब्जेक्ट मिलते हैं। अंत में, एक प्रहरी का उपयोग अत्यधिक अज्ञात है। एक प्रहरी उस पुस्तकालय के लिए विशिष्ट है जिसका उपयोग किया जाता है और जैसे कि इसका दायरा आम तौर पर पुस्तकालय के आंतरिक तक सीमित होना चाहिए। इसे "लीक" नहीं होना चाहिए। बाहरी कोड केवल इसके बारे में पता होना चाहिए, अगर उनका उद्देश्य पुस्तकालय के एपीआई का विस्तार या पूरक करना है।


किस बारे में: कोई नहीं == बात?
hkBst

@hkBst मैं आपके प्रश्न का अनुमान लगा रहा हूं कि अजगर समानता का मूल्यांकन कैसे करता है। इस stackoverflow.com/questions/3588776/…
माइकल एकोका

आह, तो IIUC कि आम तौर पर अभी भी कॉलिंग की बात खत्म हो जाएगा .__ eq__? उस स्थिति में मैं अपने सुझाव को वापस लेता हूं।
hkBst

@MichaelEkoka आप इस प्रभावशाली और उपयोगी जानकारी के लिए स्रोत साझा कर सकते हैं।
आइडिया भटनागर

मानक अभ्यास। आप पायथन ट्यूटोरियल के माध्यम से जाने से इसके कुछ संकेत पा सकते हैं , लेकिन लोकप्रिय परियोजनाओं के स्रोत कोड को पढ़ना मेरा नंबर एक सलाह है कि जल्दी से अपने आप को मुहावरेदार पायथन में डुबो दें ।
माइकल एको

67

यह अन्य भाषाओं में नल नहीं कहा है, लेकिन None। इस ऑब्जेक्ट का हमेशा एक ही उदाहरण होता है, इसलिए यदि आप चाहें, तो x is Noneइसके बजाय (पहचान की तुलना) के साथ तुल्यता की जांच कर सकते x == Noneहैं।


25
मैं पुन: तात्कालिकता करके पायथन को तोड़ने का एक तरीका खोजने जा रहा हूं None। तब उन सभी स्मार्ट लोगों की तुलना में जो NoneTypeजीत जाएगा!
Zenexer

28

पायथन में, एक मूल्य की अनुपस्थिति का प्रतिनिधित्व करने के लिए, आप स्ट्रिंग के लिए ऑब्जेक्ट्स और "" (या लेन () == 0 ) के लिए कोई भी मान ( type.NoneType.None ) का उपयोग कर सकते हैं । इसलिए:

if yourObject is None:  # if yourObject == None:
    ...

if yourString == "":  # if yourString.len() == 0:
    ...

"==" और "है" के बीच अंतर के बारे में, "==" का उपयोग करके वस्तु पहचान के लिए परीक्षण पर्याप्त होना चाहिए। हालाँकि, चूंकि ऑपरेशन "" को ऑब्जेक्ट आइडेंटिटी ऑपरेशन के रूप में परिभाषित किया गया है, संभवतः "==" के बजाय इसका उपयोग करना अधिक सही है। निश्चित नहीं है कि अगर गति में अंतर भी है।

वैसे भी, आप पर एक नज़र डाल सकते हैं:


8
जहाँ तक मुझे पता है, (0 == false) हर बार प्रोग्रामिंग भाषा में सही है। ऐसा इसलिए है क्योंकि झूठे को 0 और "सच" के रूप में कोडित किया जाता है, जो कि सब कुछ नहीं है। 0. हालांकि, कृपया यह नहीं है कि "" "ऑपरेटर" "==" के समान नहीं है। यह जावा में "==" और "बराबर" के बीच समान अंतर है। ऑपरेटर "है", वास्तव में, जांचता है कि क्या दो OBJECTS समान हैं (एक ही उदाहरण और एक ही सामग्री नहीं)!
पाओलो रूवेल्ली

12
पाओलो, FYI, (0 == गलत) हर प्रोग्रामिंग भाषा में सही नहीं होता है। एक त्वरित काउंटर उदाहरण स्काला होगा, जहां (0 == गलत) गलत है, और मुझे यकीन है कि स्काला एकमात्र प्रोग्रामिंग भाषा नहीं है जो किसी नंबर की बूलियन से तुलना करते समय झूठी रिटर्न करती है।
रोब विल्टन

2
ठीक मिल गया! फिर, आइए अधिकांश प्रोग्रामिंग भाषाओं में कहें।
पाओलो रूवेल्ली

3
जावास्क्रिप्ट में, कारण 0 == falseरिटर्न trueक्योंकि डबल-बराबर होती है ऑपरेटर प्रकार बलात्कार करता है। ट्रिपल-बराबर ऑपरेटर के साथ, हालांकि, 0 === falseरिटर्न करता है false, क्योंकि 'नंबर' और 'बूलियन' अलग-अलग प्रकार के होते हैं।
jkdev

1
@PaoloRovelli, लुआ, रूबी, और क्लोझर में 0 को trueसशर्त माना जाता है। जंग और गो में, 0और false विभिन्न प्रकार हैं जिनकी समानता के लिए तुलना नहीं की जा सकती है।
स्कूटर-

0

नल एक विशेष वस्तु प्रकार है:

>>>type(None)
<class 'NoneType'>

आप देख सकते हैं कि कोई वस्तु कक्षा में है '

>>>variable = None
>>>variable is None
True

अधिक जानकारी पायथन डॉक्स पर उपलब्ध है


-1

प्रति सत्य मूल्य परीक्षण , 'कोई नहीं' सीधे, FALSE के रूप में परीक्षण इतना सरल अभिव्यक्ति पर्याप्त होगा:

if not foo:

3
नहीं, यह नहीं होगा। वह अभिव्यक्ति किसी भी मिथ्या मूल्य के Trueलिए वापस आ जाएगी , न कि सिर्फ । None
सम्मिलित करें

सच है, और सरल "अगर नहीं फू:" मूल प्रश्न का सही उत्तर नहीं देंगे, जैसा कि कहा गया है। हालांकि, अजगर गतिशील रूप से टाइप किया गया है और वाक्यविन्यास प्रोटोकॉल को कम करने के लिए आमंत्रित करता है, इसलिए यह मेरे लिए मान्य लगता है, सरल, समान निर्माणों पर विचार करने के लिए।
आर्टीजेरा
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.