यदि यह मौजूद नहीं है, तो पायथन एक कुंजी को हुक में अपडेट करता है


108

मैं एक महत्वपूर्ण-मूल्य जोड़ी को तानाशाही में सम्मिलित करना चाहता हूँ यदि कुंजी तानाशाही में नहीं है ()। मूल रूप से मैं यह कर सकता था:

if key not in d.keys():
    d[key] = value

लेकिन क्या कोई बेहतर तरीका है? या इस समस्या का पायथोनिक समाधान क्या है?


जवाबों:


152

आपको कॉल करने की आवश्यकता नहीं है d.keys(), इसलिए

if key not in d:
    d[key] = value

पर्याप्त है। कोई स्पष्ट, अधिक पठनीय विधि नहीं है।

यदि आप dict.get()कुंजी पहले से मौजूद है, तो आप मौजूदा मूल्य के साथ फिर से अपडेट कर सकते हैं :

d[key] = d.get(key, value)

लेकिन मैं दृढ़ता से इस के खिलाफ की सिफारिश; यह कोड गोल्फिंग, रखरखाव और पठनीयता में बाधा है।


यदि मुझे कोड का उपयोग करते हुए कई थ्रेड्स हैं, तो क्या मुझे इसे सिंक्रनाइज़ करने की आवश्यकता है?
ed22

1
@ ed22 हाँ, क्योंकि इसमें कई बाइटकोड निर्देश शामिल हैं, जिनके बीच में थ्रेड्स स्विच कर सकते हैं।
मार्टिज़न पीटरर्स

84

उपयोग करें dict.setdefault():

>>> d = {1: 'one'}
>>> d.setdefault(1, '1')
'one'
>>> d    # d has not changed because the key already existed
{1: 'one'}
>>> d.setdefault(2, 'two')
'two'
>>> d
{1: 'one', 2: 'two'}

6
dict.setdefault()वास्तव में केवल तब उपयोग किया जाना चाहिए जब मूल्य भी एक्सेस करने की कोशिश कर रहा हो।
मार्टिन पीटर्स

14
@MartijnPieters: वह बात क्यों करता है? नाम setdefault()स्पष्ट रूप से बताता है कि क्या हो रहा है - कि यह एक मूल्य भी लौटाता है वह महत्वपूर्ण नहीं है, और थोड़ा विचित्र आईएमओ है। क्या आप एक त्वरित स्पष्टीकरण या एक लिंक प्रदान कर सकते हैं, जैसे कि यह वांछनीय क्यों नहीं है?
फव्वारा

6
आप इसे एक अभिव्यक्ति में उपयोग करेंगे जो एक समूह लूप में मौजूद होने के लिए एक मूल्य की अपेक्षा करता है for obj in iterable: d.setdefault(key_for_obj(obj), []).append(obj):। मूल्य वापस किए जाने के बारे में कुछ भी स्पष्ट नहीं है, यह विधि का पूरा बिंदु है
मार्टिन पीटर्स

2
इसके अलावा, यह अस्पष्ट कर देता है कि आप क्या करने की कोशिश कर रहे हैं, जो कि एक कुंजी सेट करना है यदि यह पहले से मौजूद नहीं है। पठनीयता मायने रखती है, बस एक if key not in d:परीक्षण का उपयोग करें ।
मार्टिन पीटर्स

7
@MartijnPieters: स्पष्टीकरण के लिए धन्यवाद। डॉकस्ट्रिंग को पढ़ने के बाद, setdefault()आपने जो कहा है , उसके अनुरूप है। ए का उपयोग करने defaultdict(list)से आपके उदाहरण से अधिक पठनीय कोड होता है ... इसलिए शायद इसका कोई उपयोग नहीं है जब तक कि मानक शब्दकोशों के साथ काम नहीं करना चाहिए। कुल मिलाकर, if key not in dस्पष्ट है।
फव्वारा

25

पायथन 3.9 के बाद से आप मर्ज ऑपरेटर | का उपयोग दो शब्दकोशों को मर्ज करने के लिए कर सकते हैं । दाईं ओर का ताना-बाना पूर्वगामी होता है:

new_dict = old_dict | { key: val }

उदाहरण के लिए:

new_dict = { 'a': 1, 'b': 2 } | { 'b': 42 }

print(new_dict} # {'a': 1, 'b': 42}

नोट: यह अद्यतन मूल्यों के साथ एक नया शब्दकोश बनाता है।


6
हालांकि यह दिलचस्प है, मुझे नहीं लगता कि यह स्वीकृत उत्तर की तुलना में अधिक पठनीय है
जस्टिन फुरुनस

2
मेरे लिए, यह जानना अच्छा है कि अब दो डिसर्ट को मर्ज करने का एक तरीका है
ऑस्टिन ए

इस मर्ज के साथ एक चुनौती है। यदि कुंजियाँ समान हैं, तो मर्ज मान को अनदेखा कर देगा। यदि वह इरादा है, तो यह काम करता है।
जो फेरडज

1
@JoeFerndz दाईं ओर स्थित पूर्ववर्तीता लेता है और मूल्य को अनदेखा नहीं करेगा। मैंने इसे और अधिक स्पष्ट करने के लिए उदाहरण को अद्यतन किया।
रोटारती

6

निम्नलिखित के साथ आप कई मान सम्मिलित कर सकते हैं और डिफ़ॉल्ट मान भी रख सकते हैं लेकिन आप एक नया शब्दकोश बना रहे हैं।

d = {**{ key: value }, **default_values}

मैंने इसे सबसे अधिक वोट किए गए उत्तर के साथ परीक्षण किया है और औसतन यह तेज़ है क्योंकि इसे निम्नलिखित उदाहरण में देखा जा सकता है,

अनपैक ऑपरेटर के साथ एक तानाशाही समझ के साथ लूप आधारित विधि के लिए तुलना करते हुए स्पीड टेस्ट गति परीक्षण अनपैक ऑपरेटर विधि के साथ एक तानाशाही समझ के साथ लूप आधारित विधि के लिए तुलना करता है।

यदि d = default_vals.copy()पहले मामले पर कोई प्रतिलिपि ( ) नहीं बनाई गई है, तो सबसे अधिक मतदान का उत्तर तेजी से 10**5और अधिक से अधिक के आदेशों तक पहुंचने के बाद होगा । दोनों विधियों की मेमोरी पदचिह्न समान हैं।


1
तो फिर इसे पहले स्थान पर क्यों
जोनाथन

1
यह समाधान मुझे पूरी तरह से मान्य लगता है। यह एक घोषणा में कई मूल्यों को अपडेट करने की भी अनुमति देता है।
रोटारटी

बहुत बहुत धन्यवाद। लेकिन ऐसा लगता है{**default_values, **{ key: value }}
osexp2003

0

उपरोक्त उत्तरों के अनुसार सेटडेफॉल्ट () विधि ने मेरे लिए काम किया।

old_attr_name = mydict.setdefault(key, attr_name)
if attr_name != old_attr_name:
    raise RuntimeError(f"Key '{key}' duplication: "
                       f"'{old_attr_name}' and '{attr_name}'.")

हालांकि यह समाधान सामान्य नहीं है। बस मुझे इस निश्चित मामले में अनुकूल। सटीक समाधान keyपहले के लिए जाँच करेगा (जैसा कि पहले से ही सलाह दी गई थी), लेकिन setdefault()हम शब्दकोश में एक अतिरिक्त खोज से बचते हैं, हालांकि यह छोटा है, लेकिन अभी भी एक प्रदर्शन लाभ है।

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