एक शब्दकोश के लिए पायथन "विस्तार"


462

किसी दूसरे के साथ एक शब्दकोश का विस्तार करने का सबसे अच्छा तरीका कौन सा है? उदाहरण के लिए:

>>> a = { "a" : 1, "b" : 2 }
>>> b = { "c" : 3, "d" : 4 }
>>> a
{'a': 1, 'b': 2}
>>> b
{'c': 3, 'd': 4}

इस forलूप से बचने के लिए मैं किसी भी ऑपरेशन की तलाश कर रहा हूं :

{ "a" : 1, "b" : 2, "c" : 3, "d" : 4 }

मैं कुछ ऐसा करना चाहता हूं:

a.extend(b)  # This does not work

25
मैं सूचियों के लिए जानता था [], तो मैं दूसरों के लिए काम कर सकता हूं, एक्सट्रेंज नहीं;;
फेरनब

जवाबों:


694

6
डॉक्स पढ़ने के बाद कोई भी समझ जाएगा कि क्यों एक ´update one है लेकिन कोई dextend´ नहीं है।
जियोर्गा

58
ध्यान रखें कि अपडेट () सीधे डिक्टेट को संशोधित करता है और कोई नहीं लौटाता है।
e18r

5
लेकिन क्या होगा यदि आप केवल उन मानों के साथ तानाशाही का विस्तार करना चाहते हैं जो पहले से परिभाषित नहीं हैं (अर्थात मौजूदा मूल्यों को अधिलेखित नहीं करना)? उदाहरण के लिए, एक तानाशाह {"a":2, "b":3}को तानाशाही {"b":4, "c":5}से अपडेट करें {"a":2, "b":3,"c":5}? बेशक यह update()कुछ सामानों को इधर-उधर करके उपयोग करना संभव है , लेकिन यह अच्छा होगा यदि इसे केवल एक लाइन में पूरा किया जा सके ...
नीरोओ

17
@ नीरो - बस विपरीत तरीके से अपडेट करें; इसके बजाय x.update (y) [जो y के साथ x मानों को अधिलेखित करेगा], y.update (x) [जो x के साथ y मानों को अधिलेखित करता है] का उपयोग करें और आगे के संचालन के लिए y को आपके चुने हुए तानाशाह के रूप में उपयोग करें
jonathanate

ध्यान रखें कि updateचुपचाप मौजूदा प्रविष्टियों को अधिलेखित कर दें। यानी, ओवरलैपिंग कीज़ के लिए इन्हें bअधिलेखित करने का कोई मूल्य a
CGFoX

186

इस बंद प्रश्न में एक सुंदर रत्न :

"Oneliner तरीका", इनपुट dicts में से किसी में भी फेरबदल नहीं है

basket = dict(basket_one, **basket_two)

जानें कि **basket_two( **) का क्या अर्थ है

संघर्ष के मामले में, से आइटम लोगों basket_twoको ओवरराइड करेगा basket_one। जैसा कि वन-लाइनर्स जाते हैं, यह बहुत पठनीय और पारदर्शी है, और मुझे किसी भी समय इसका उपयोग करने के खिलाफ कोई कंपीटीशन नहीं है, जो दो अन्य लोगों के मिश्रण में काम आता है (कोई भी पाठक जिसे समझने में परेशानी होती है, वह वास्तव में बहुत अच्छी तरह से काम करेगा। जिस तरह से यह उसे dictऔर **फॉर्म के बारे में सीखने की ओर संकेत करता है; ;-)। इसलिए, उदाहरण के लिए, जैसे उपयोग करता है:

x = mungesomedict(dict(adict, **anotherdict))

मेरे कोड में यथोचित बारंबारताएँ हैं।

मूल रूप से एलेक्स मार्टेली द्वारा प्रस्तुत किया गया

नोट: पायथन 3 में, यह केवल तभी काम करेगा जब टोकरी_टू में प्रत्येक कुंजी a हो string


3
इसके लिए दस्तावेज़ीकरण dictकरना आसान है, जबकि **थोड़ा और मुश्किल है (कीवर्ड kwargs है )। यहाँ एक अच्छी व्याख्या है: saltycrane.com/blog/2008/01/…
johndodo

4
इसका उपयोग एक एकल कमांड के साथ दूसरा चर उत्पन्न करने के लिए किया जा सकता है, जबकि basket_one.update(<dict>)जैसा कि नाम ने कहा, एक मौजूदा शब्दकोश (या एक क्लोन एक) को अपडेट करता है।
16

2
ध्यान दें कि पायथन 3 में, तर्क नाम, और इस प्रकार की कुंजी **anotherdict, तार होना चाहिए।
पेट्र विक्टोरियन

धन्यवाद @johndodo - मैंने आपके सुझावों को पोस्ट में एकीकृत कर दिया है।
टॉम लेन्स

1
स्वीकृत उत्तर के लिए एक अच्छा कार्यात्मक विकल्प। यह दृष्टिकोण वांछनीय है यदि आपको सीधे नए संयुक्त तानाशाही का उपयोग करने की आवश्यकता है। (स्वीकृत उत्तर पर @ e18r की टिप्पणी भी देखें)।
चिन्नीचिनचिन

45

क्या आपने शब्दकोश मानचित्रण के साथ शब्दकोश समझ का उपयोग करने की कोशिश की है:

a = {'a': 1, 'b': 2}
b = {'c': 3, 'd': 4}

c = {**a, **b}
# c = {"a": 1, "b": 2, "c": 3, "d": 4}

करने का एक और तरीका है तानाशाही (पुनरावृत्ति, ** कर्ग) का उपयोग करना

c = dict(a, **b)
# c = {'a': 1, 'b': 2, 'c': 3, 'd': 4}

Python 3.9 में आप संघ का उपयोग करके दो तानाशाह जोड़ सकते हैं | ऑपरेटर

# use the merging operator |
c = a | b
# c = {'a': 1, 'b': 2, 'c': 3, 'd': 4}

5
FYI करें: यह पायथन 2.7 में मान्य सिंटैक्स नहीं है
असाव पटेल

2
यह वाक्यविन्यास काफी नया है (पायथन 3.5)
पियानोजम्स

24
a.update(b)

से कुंजी और मूल्यों जोड़ देगा के लिए एक , वहाँ पहले से ही एक कुंजी के लिए एक मूल्य है कि अगर अधिलेखित।


17

के रूप में दूसरों का उल्लेख किया है, a.update(b)कुछ dicts के लिए aऔर bपरिणाम आप अपने प्रश्न में के लिए कहा है प्राप्त करेंगे। हालांकि, मैं करते रहे कि कई बार मैंने देखा है चाहता हूँ extendमैपिंग की विधि / सेट वस्तुओं की इच्छा वाक्य रचना में a.extend(b), aके मूल्यों नहीं द्वारा ओवरराइट किया जाना चाहिए bरों मूल्यों '। मूल्यों को a.update(b)अधिलेखित aकरता है, और इसलिए इसके लिए एक अच्छा विकल्प नहीं है extend

ध्यान दें कि कुछ भाषाएं इस विधि को defaultsया inject, क्योंकि इसे बी के मूल्यों को इंजेक्ट करने के तरीके के रूप में माना जा सकता है (जो कि डिफ़ॉल्ट मानों का एक सेट हो सकता है) एक शब्दकोश में बिना ओवर राइटिंग मूल्यों के पहले से मौजूद हो सकता है।

बेशक, आप सरल नोट कर सकते हैं जो a.extend(b)लगभग उसी तरह है b.update(a); a=b। असाइनमेंट को हटाने के लिए, आप इसे इस प्रकार कर सकते हैं:

def extend(a,b):
    """Create a new dictionary with a's properties extended by b,
    without overwriting.

    >>> extend({'a':1,'b':2},{'b':3,'c':4})
    {'a': 1, 'c': 4, 'b': 2}
    """
    return dict(b,**a)

टॉम लेय्स के लिए धन्यवाद कि स्मार्ट विचार के लिए एक साइड-इफेक्ट-कम dictकंस्ट्रक्टर का उपयोग कर रहा है extend


1

आप अजगर के संग्रह का भी उपयोग कर सकते हैं। इनचैंपमैप जो अजगर 3.3 में पेश किया गया था।

from collections import Chainmap
c = Chainmap(a, b)
c['a'] # returns 1

आपके उपयोग-मामले के आधार पर इसके कुछ संभावित फायदे हैं। उन्हें यहां और अधिक विस्तार से समझाया गया है , लेकिन मैं एक संक्षिप्त विवरण दूंगा:

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

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


0

यदि आपको कक्षा के रूप में इसकी आवश्यकता है , तो आप इसे तानाशाही के साथ आगे बढ़ा सकते हैं और अद्यतन विधि का उपयोग कर सकते हैं :

Class a(dict):
  # some stuff
  self.update(b)
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.