क्या एक पायथन सी # नल-सह-संचालन ऑपरेटर के बराबर है?


301

C # में एक अशक्त-संचालक संचालक है (जैसा लिखा गया है ??) जो असाइनमेंट के दौरान आसान (छोटी) अशक्त जाँच की अनुमति देता है:

string s = null;
var other = s ?? "some default value";

क्या एक अजगर बराबर है?

मुझे पता है कि मैं कर सकता हूं:

s = None
other = s if s else "some default value"

लेकिन वहाँ भी एक छोटा रास्ता है (जहां मुझे दोहराने की आवश्यकता नहीं है s)?


14
??ऑपरेटर के रूप में प्रस्तावित किया गया है पीईपी 505
२००

जवाबों:


421
other = s or "some default value"

ठीक है, यह स्पष्ट किया जाना चाहिए कि orऑपरेटर कैसे काम करता है। यह एक बूलियन ऑपरेटर है, इसलिए यह बूलियन संदर्भ में काम करता है। यदि मान बूलियन नहीं हैं, तो वे ऑपरेटर के उद्देश्यों के लिए बूलियन में परिवर्तित हो जाते हैं।

ध्यान दें कि orऑपरेटर केवल Trueया नहीं लौटाता है False। इसके बजाय, यह पहला ऑपरेंड लौटाता है यदि पहला ऑपरेंड सच का मूल्यांकन करता है, और यह दूसरा ऑपरेंड लौटाता है अगर पहला ऑपरेंड गलत का मूल्यांकन करता है।

इस मामले में, अभिव्यक्ति x or yवापस आ जाती है xयदि यह है Trueया बूलियन में परिवर्तित होने पर सच का मूल्यांकन करता है। नहीं तो लौट आता है y। अधिकांश मामलों के लिए, यह C n के अशक्त-सहवर्ती ऑपरेटर के बहुत ही उद्देश्य के लिए काम करेगा, लेकिन ध्यान रखें:

42    or "something"    # returns 42
0     or "something"    # returns "something"
None  or "something"    # returns "something"
False or "something"    # returns "something"
""    or "something"    # returns "something"

यदि आप अपने वैरिएबल sका उपयोग किसी ऐसी चीज को रखने के लिए करते हैं जो या तो किसी वर्ग के उदाहरण के संदर्भ में है या None(जब तक आपकी कक्षा सदस्यों को परिभाषित नहीं करती है __nonzero__()और __len__()), उसी शब्दार्थ को शून्य-सहवर्ती ऑपरेटर के रूप में उपयोग करना सुरक्षित है।

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

कुछ भाषाओं में इस व्यवहार को एल्विस ऑपरेटर कहा जाता है ।


3
क्या यह वही काम करेगा? मेरा मतलब है, क्या यह sवैध मूल्य होने पर टूट जाएगा लेकिन सत्य नहीं है? (मैं पायथन को नहीं जानता, इसलिए मुझे यकीन नहीं है कि क्या '
सत्य

9
संख्या 0, Noneऔर खाली कंटेनरों (तार सहित) को स्थिर के अलावा, झूठा माना जाता है False। बाकी सब कुछ सच माना जाता है। मैं कहूंगा कि यहां मुख्य खतरा यह होगा कि आपको एक सच्चा लेकिन गैर-स्ट्रिंग मूल्य मिलेगा, लेकिन यह कुछ कार्यक्रमों में एक मुद्दा नहीं होगा।
किंडल

25
अन्य का उपयोग करने पर डिफ़ॉल्ट मान मिलेगा यदि कोई भी नहीं है या गलत है , जो वह नहीं है जो वह चाहता है।
पफस्कु

6
इसके कारण कई अस्पष्ट कीड़े भी हैं। उदाहरण के लिए पाइथन 3.5 से पहले, datetime.time(0)भी झूठा था!
अंती हापाला

19
ये गलत है। मैं इसके नुकसान के बारे में एक नोटिस जोड़ने की सलाह देता हूं। और इसका इस्तेमाल करने की सलाह दे रहे हैं।
मतीन उल्हाक

61

सख्ती से,

other = s if s is not None else "default value"

अन्यथा, s = Falseबन जाएगा "default value", जो कि इरादा नहीं था हो सकता है।

यदि आप इसे कम करना चाहते हैं, तो कोशिश करें:

def notNone(s,d):
    if s is None:
        return d
    else:
        return s

other = notNone(s, "default value")

1
Consider x()?.y()?.z()
नुरेटिन

40

यहाँ एक फ़ंक्शन है जो पहला तर्क लौटाएगा जो नहीं है None:

def coalesce(*arg):
  return reduce(lambda x, y: x if x is not None else y, arg)

# Prints "banana"
print coalesce(None, "banana", "phone", None)

reduce()सभी तर्कों पर अनावश्यक रूप से पुनरावृत्ति हो सकती है, भले ही पहला तर्क न हो None, इसलिए आप इस संस्करण का भी उपयोग कर सकते हैं:

def coalesce(*arg):
  for el in arg:
    if el is not None:
      return el
  return None

23
def coalesce(*arg): return next((a for a in arg if a is not None), None)एक पंक्ति में अपने अंतिम उदाहरण के समान है।
ग्लोगल

2
मुझे लगता है कि लोग समझाना चाहते हैं कि क्या सिंटैक्स आदि हैं, लेकिन मोटे तौर पर एक मनमानी तर्क सूची होती है, इसलिए यह वास्तव में शीर्ष उत्तर होना चाहिए।
एरिक ट्विलेगर

2
glglgl का सबसे अच्छा जवाब है। मैंने एक बड़े परीक्षण सरणी पर टाइमिट का उपयोग किया और कम कार्यान्वयन अस्वीकार्य रूप से धीमा है, यदि संस्करण सबसे तेज़ है, या यदि संस्करण सबसे तेज़ है, और अगला कार्यान्वयन बहुत थोड़ा पीछे है। सरलता और संक्षिप्तता पर विचार करते हुए अगला संस्करण सबसे अच्छा है।
मिट्टी

3
@glglgl में दिलचस्प स्निपेट है। दुर्भाग्य से क्योंकि पायथन का पास-बाय-नेम नहीं है, इसलिए इस तरह के सह-संबंध कम-चक्कर नहीं हैं; कोड के चलने से पहले सभी तर्कों का मूल्यांकन किया जाता है।
user1338062

Consider x()?.y()?.z()
नुरेटिन

5

मुझे पता है कि यह उत्तर दिया गया है, लेकिन जब आप वस्तुओं के साथ काम कर रहे हैं तो एक और विकल्प है।

यदि आपके पास एक वस्तु है जो हो सकती है:

{
   name: {
      first: "John",
      last: "Doe"
   }
}

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

obj.get(property_name, value_if_null)

पसंद:

obj.get("name", {}).get("first", "Name is missing") 

{}डिफ़ॉल्ट मान के रूप में जोड़कर , यदि "नाम" गायब है, तो एक खाली वस्तु वापस आ जाती है और अगले प्राप्त करने के लिए पारित हो जाती है। यह C # में null-safe-navigation के समान है, जो कि जैसा होगा obj?.name?.first


सभी वस्तुओं के पास नहीं है .get, यह केवल
तानाशाह

मैं एक उत्तर संपादित करने के लिए getattr()भी प्रस्तुत कर रहा हूँ ।
dgw

getयदि मान कोई नहीं है, तो डिफ़ॉल्ट पर डिफ़ॉल्ट पैरामीटर का उपयोग नहीं करता है, लेकिन मान मौजूद नहीं होने के कारण डिफ़ॉल्ट पैरामीटर का उपयोग करता है। परिणाम के रूप में {'a': None}.get('a', 'I do not want None')आप अभी भी दे देंगे None
पैट्रिक मेव्ज़ेक

3

"या" के व्यवहार के बारे में जूलियानो के जवाब के अलावा: यह "तेज" है

>>> 1 or 5/0
1

तो कभी-कभी यह चीजों के लिए एक उपयोगी शॉर्टकट हो सकता है

object = getCachedVersion() or getFromDB()

17
आपके द्वारा खोजा जा रहा शब्द "शॉर्ट-सर्किट" है।
jpmc26

1

संभवतः एकल मानों के लिए @Bothwells उत्तर (जो मुझे पसंद है), फ़ंक्शन रिटर्न मानों की अशक्तता की जांच करने के लिए, आप नए वालरस-ऑपरेटर (python3.8 के बाद से) का उपयोग कर सकते हैं:

def test():
    return

a = 2 if (x:= test()) is None else x

इस प्रकार, testफ़ंक्शन को दो बार मूल्यांकन करने की आवश्यकता नहीं है (जैसा कि a = 2 if test() is None else test())


1

मामले में आप एक से अधिक अशक्त coलेसिंग ऑपरेशन घोंसला बनाने की जरूरत है:

model?.data()?.first()

यह आसानी से हल होने वाली समस्या नहीं है or। यह भी हल नहीं किया जा सकता है .get()जिसके साथ एक शब्दकोश प्रकार या समान (और वैसे भी नेस्टेड नहीं किया जा सकता है) की आवश्यकता होती है या getattr()जो कोई अपवाद नहीं है जब कोई विशेषता नहीं होगी।

संबंधित पाइप को भाषा में अशक्त जोड़ने पर विचार PEP 505 है और दस्तावेज़ से संबंधित चर्चा अजगर-विचारों के धागे में है।


0

@Hghgh Bothwell, @mortehu और @glglgl द्वारा जवाब के बारे में।

परीक्षण के लिए डेटासेट सेट करें

import random

dataset = [random.randint(0,15) if random.random() > .6 else None for i in range(1000)]

कार्यान्वयन को परिभाषित करें

def not_none(x, y=None):
    if x is None:
        return y
    return x

def coalesce1(*arg):
  return reduce(lambda x, y: x if x is not None else y, arg)

def coalesce2(*args):
    return next((i for i in args if i is not None), None)

परीक्षण कार्य करें

def test_func(dataset, func):
    default = 1
    for i in dataset:
        func(i, default)

Python 2.7 का उपयोग करके मैक i7 @ 2.7Ghz पर परिणाम

>>> %timeit test_func(dataset, not_none)
1000 loops, best of 3: 224 µs per loop

>>> %timeit test_func(dataset, coalesce1)
1000 loops, best of 3: 471 µs per loop

>>> %timeit test_func(dataset, coalesce2)
1000 loops, best of 3: 782 µs per loop

स्पष्ट रूप से not_noneफ़ंक्शन ओपी के प्रश्न का सही उत्तर देता है और "झूठी" समस्या को संभालता है। यह पढ़ने में सबसे तेज और आसान भी है। यदि कई स्थानों पर तर्क को लागू करते हैं, तो यह स्पष्ट रूप से जाने का सबसे अच्छा तरीका है।

यदि आपको कोई समस्या है जहाँ आप 1 गैर-अशक्त मान को एक पुनरावृत्त में ढूंढना चाहते हैं, तो @ mortehu की प्रतिक्रिया जाने का मार्ग है। लेकिन यह ओपी की तुलना में एक अलग समस्या का समाधान है , हालांकि यह आंशिक रूप से उस मामले को संभाल सकता है। यह एक iterable और एक डिफ़ॉल्ट मान नहीं ले सकता। अंतिम तर्क होगा डिफ़ॉल्ट मान लौटा, लेकिन तब आप उस स्थिति में एक पुनरावृत्ति में पास नहीं होंगे और साथ ही यह स्पष्ट नहीं होगा कि अंतिम तर्क मान के लिए डिफ़ॉल्ट है।

फिर आप नीचे कर सकते हैं, लेकिन मैं अभी भी not_nullएकल मूल्य उपयोग मामले के लिए उपयोग करूंगा ।

def coalesce(*args, **kwargs):
    default = kwargs.get('default')
    return next((a for a in arg if a is not None), default)

0

मेरे जैसे उन लोगों के लिए जो इस मुद्दे पर एक व्यवहार्य समाधान की तलाश कर रहे थे, जब चर अपरिभाषित हो सकता है, तो मुझे जो निकटतम मिला वह है:

if 'variablename' in globals() and ((variablename or False) == True):
  print('variable exists and it\'s true')
else:
  print('variable doesn\'t exist, or it\'s false')

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

चर अस्तित्व पर अधिक: अगर चर मौजूद है तो मैं कैसे जांच करूं?


1
(variablename or False) == Trueके रूप में ही हैvariablename == True
mic

-2
Python has a get function that its very useful to return a value of an existent key, if the key exist;
if not it will return a default value.

def main():
    names = ['Jack','Maria','Betsy','James','Jack']
    names_repeated = dict()
    default_value = 0

    for find_name in names:
        names_repeated[find_name] = names_repeated.get(find_name, default_value) + 1

यदि आपको शब्दकोश के अंदर नाम नहीं मिल रहा है, तो वह default_value लौटा देगा, यदि नाम मौजूद है तो यह 1 के साथ कोई भी मौजूदा मान जोड़ देगा।

आशा है कि यह मदद कर सकता है


1
नमस्ते, ढेर अतिप्रवाह में आपका स्वागत है। आपका उत्तर कौन सी नई जानकारी जोड़ता है जो पहले से ही मौजूदा उत्तरों द्वारा कवर नहीं किया गया था? उदाहरण के लिए @ क्रेग का उत्तर देखें
ग्रैसी

-6

नीचे दिए गए दो फ़ंक्शंस मैंने कई वेरिएबल टेस्टिंग मामलों से निपटने के दौरान बहुत उपयोगी माने हैं।

def nz(value, none_value, strict=True):
    ''' This function is named after an old VBA function. It returns a default
        value if the passed in value is None. If strict is False it will
        treat an empty string as None as well.

        example:
        x = None
        nz(x,"hello")
        --> "hello"
        nz(x,"")
        --> ""
        y = ""   
        nz(y,"hello")
        --> ""
        nz(y,"hello", False)
        --> "hello" '''

    if value is None and strict:
        return_val = none_value
    elif strict and value is not None:
        return_val = value
    elif not strict and not is_not_null(value):
        return_val = none_value
    else:
        return_val = value
    return return_val 

def is_not_null(value):
    ''' test for None and empty string '''
    return value is not None and len(str(value)) > 0

5
इस तरह की चीजें थोड़ा अलग शब्दावली का एक पूरा गुच्छा जोड़ती हैं (उदाहरण के लिए "null" और "nz" जिनमें से न तो पायथन के संदर्भ में कुछ भी मतलब है), अन्य भाषाओं से आयातित, साथ ही वेरिएंट (सख्त या गैर-सख्त!) के साथ। यह केवल भ्रम जोड़ता है। स्पष्ट है "कोई नहीं" चेक वह हैं जो आपको उपयोग करना चाहिए। साथ ही आपको किसी भी शॉर्ट-कटिंग शब्दार्थ का लाभ नहीं मिलता है जो ऑपरेटर्स तब कर सकते हैं जब आप फ़ंक्शन कॉल का उपयोग करते हैं।
spookylukey
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.