कैसे एक शब्दकोश कॉपी और केवल कॉपी को संपादित करने के लिए


852

क्या कोई मुझसे इसकी व्याख्या करेगा? इससे मुझे कोई मतलब नहीं है।

मैं एक शब्दकोश को दूसरे में कॉपी करता हूं और दूसरे को संपादित करता हूं और दोनों को बदल दिया जाता है। ये क्यों हो रहा है?

>>> dict1 = {"key1": "value1", "key2": "value2"}
>>> dict2 = dict1
>>> dict2
{'key2': 'value2', 'key1': 'value1'}
>>> dict2["key2"] = "WHY?!"
>>> dict1
{'key2': 'WHY?!', 'key1': 'value1'}

3
PythonTutor पायथन संदर्भों को देखने के लिए बहुत अच्छा है। यह कोड अंतिम चरण में है । आप उसी तानाशाह को देख dict1और dict2इशारा कर सकते हैं ।
wjandrea 13

जवाबों:


881

अजगर कभी भी वस्तुओं की नकल नहीं करता है । जब आप सेट dict2 = dict1करते हैं, तो आप उन्हें उसी सटीक कमांड ऑब्जेक्ट का संदर्भ दे रहे होते हैं, इसलिए जब आप इसे म्यूट करते हैं, तो इसके सभी संदर्भ ऑब्जेक्ट को इसकी वर्तमान स्थिति में संदर्भित करते रहते हैं।

यदि आप हुकुम की नकल करना चाहते हैं (जो दुर्लभ है), तो आपको स्पष्ट रूप से ऐसा करना होगा

dict2 = dict(dict1)

या

dict2 = dict1.copy()

26
यह कहने के लिए बेहतर हो सकता है कि "डिक्सेस 2 और डिक्ट 1 पॉइंट एक ही डिक्शनरी में कहें ", आप डिक्ट 1 या डिक्ट 2 नहीं बदल रहे हैं, लेकिन क्या बात करते हैं।
ग्रेवॉर्क्सएक्स

275
यह भी ध्यान दें कि डिक्टेड.कॉपी () उथला है, अगर कोई नेस्टेड सूची / आदि है तो दोनों में परिवर्तन लागू होंगे। IIRC। दीपावली से बचेंगे।
विल

16
यह बिल्कुल सही नहीं है कि अजगर कभी भी वस्तुओं की नकल नहीं करता है। आदिम डेटा प्रकार, जैसे कि इंट, फ्लोट, और बूल को भी ऑब्जेक्ट के रूप में माना जाता है (बस इसे dir(1)देखने के लिए एक ), लेकिन वे अंतर्निहित रूप से कॉपी किए जाते हैं।
डैनियल कुल्मन

17
@danielkullmann, मुझे लगता है कि आप पायथन के बारे में गलतफहमी पा सकते हैं कि आपने अन्य भाषाओं के साथ काम कैसे किया है। पायथन में, क) "आदिम डेटा प्रकार" की कोई अवधारणा नहीं है। int, floatऔर boolउदाहरण वास्तविक पायथन ऑब्जेक्ट्स हैं, और बी) इन प्रकारों की वस्तुओं को अंतर्निहित रूप से कॉपी नहीं किया जाता है जब आप उन्हें पास करते हैं, निश्चित रूप से सिमेंटिक पायथन स्तर पर नहीं और सीपीथॉन में कार्यान्वयन विवरण के रूप में भी नहीं।
माइक ग्राहम

39
"डीप कॉपी को हानिकारक माना जाता है" जैसी असंस्कारी बयानबाजी बेकार है। और सभी समान हैं, उथले एक जटिल डेटा संरचना को कॉपी है काफी अधिक गहरी उसी संरचना प्रति बनाने की बजाय अप्रत्याशित बढ़त मामले मुद्दों उपज की संभावना है। एक प्रति जिसमें संशोधन मूल वस्तु को संशोधित करता है वह प्रति नहीं है; यह एक बग है। Ergo, सबसे उपयोग के मामलों बिल्कुल चाहिए फोन copy.deepcopy()के बजाय dict()या dict.copy()इमरान का संक्षिप्त जवाब इस जवाब के विपरीत, विवेक के दाईं ओर है।
सेसिल करी

645

जब आप असाइन करते हैं dict2 = dict1, तो आप उसकी प्रतिलिपि नहीं बना रहे हैं dict1, इसका परिणाम dict2केवल एक और नाम होना है dict1

शब्दकोशों के परस्पर प्रकारों को कॉपी करने के लिए मॉड्यूल का उपयोग करें copy/ करें ।deepcopycopy

import copy

dict2 = copy.deepcopy(dict1)

80
किसी भी शब्दकोश के लिए मैं कभी भी साथ काम करता हूं, डीपकोपी वह है जिसकी मुझे आवश्यकता है ... मैंने बग के कारण कई घंटे खो दिए, क्योंकि मुझे नेस्टेड डिक्शनरी की पूरी कॉपी नहीं मिल रही थी और नेस्टेड प्रविष्टियों में मेरे बदलाव मूल को प्रभावित कर रहे थे। ।
flutefreak7

7
मुझे भी। deepcopy () ट्रिक करता है। मूल घटना के एक 'कॉपी' के लिए टाइमस्टैम्प जोड़कर एक घूर्णन कैश के अंदर मेरे नेस्टेड dicts को गड़बड़ कर रहा था। धन्यवाद!
fxstein

8
इसे वास्तव में सही उत्तर के रूप में चिह्नित किया जाना चाहिए; यह उत्तर सामान्य है और यह शब्दकोशों के शब्दकोश के लिए भी काम करता है।
orezvani

30
यह स्वीकृत उत्तर होना चाहिए। असंतुष्ट "डीप कॉपी को हानिकारक माना जाता है" वर्तमान स्वीकार किए गए उत्तर के टिप्पणी अनुभाग में एम्बेडेड बयानों को ब्लास्ट किए गए सिंक्रोनाइज़ेशन वॉयस को कॉपी करता है, जब नेस्टेड डिक्शनरी (जैसे कि यहां डॉक्यूमेंट किए गए) को कॉपी किया जाना चाहिए और इस तरह से चुनौती दी जानी चाहिए।
सेसिल करी

डीपकोपी एक जटिल शब्दकोश संरचना के मामले में जाने का तरीका है। dict1.copy () केवल संदर्भों के रूप में कुंजी के मूल्यों को कॉपी करता है न कि वस्तुओं के रूप में।
रोहित एन

182

जबकि dict.copy()और dict(dict1)एक प्रति उत्पन्न करता है, वे केवल उथली प्रतियां हैं। यदि आप एक गहरी प्रतिलिपि चाहते हैं , copy.deepcopy(dict1)तो आवश्यक है। एक उदाहरण:

>>> source = {'a': 1, 'b': {'m': 4, 'n': 5, 'o': 6}, 'c': 3}
>>> copy1 = x.copy()
>>> copy2 = dict(x)
>>> import copy
>>> copy3 = copy.deepcopy(x)
>>> source['a'] = 10  # a change to first-level properties won't affect copies
>>> source
{'a': 10, 'c': 3, 'b': {'m': 4, 'o': 6, 'n': 5}}
>>> copy1
{'a': 1, 'c': 3, 'b': {'m': 4, 'o': 6, 'n': 5}}
>>> copy2
{'a': 1, 'c': 3, 'b': {'m': 4, 'o': 6, 'n': 5}}
>>> copy3
{'a': 1, 'c': 3, 'b': {'m': 4, 'o': 6, 'n': 5}}
>>> source['b']['m'] = 40  # a change to deep properties WILL affect shallow copies 'b.m' property
>>> source
{'a': 10, 'c': 3, 'b': {'m': 40, 'o': 6, 'n': 5}}
>>> copy1
{'a': 1, 'c': 3, 'b': {'m': 40, 'o': 6, 'n': 5}}
>>> copy2
{'a': 1, 'c': 3, 'b': {'m': 40, 'o': 6, 'n': 5}}
>>> copy3  # Deep copy's 'b.m' property is unaffected
{'a': 1, 'c': 3, 'b': {'m': 4, 'o': 6, 'n': 5}}

उथले बनाम गहरी प्रतियों के बारे में, पायथन copyमॉड्यूल डॉक्स से :

उथली और गहरी नकल के बीच का अंतर केवल यौगिक वस्तुओं के लिए प्रासंगिक है (ऐसी वस्तुएं जिनमें अन्य वस्तुएं होती हैं, जैसे सूची या वर्ग उदाहरण):

  • उथली प्रतिलिपि एक नई यौगिक वस्तु का निर्माण करती है और फिर (संभव सीमा तक) मूल में पाई जाने वाली वस्तुओं में संदर्भ डालती है।
  • एक गहरी प्रतिलिपि एक नई यौगिक वस्तु का निर्माण करती है और फिर, पुनरावर्ती रूप से, मूल में पाई जाने वाली वस्तुओं में प्रतियों को सम्मिलित करती है।

2
यह सही उत्तर होना चाहिए क्योंकि यह स्पष्ट रूप से हुक पर लूप नहीं करता है और इसका उपयोग अन्य प्राथमिक संरचनाओं के लिए किया जा सकता है।
निकोलसग

27
बस स्पष्ट करने के लिए: w=copy.deepcopy(x)कुंजी लाइन है।
शराबी

बीच क्या अंतर है dict2 = dict1और dict2 = copy.deepcopy(dict1)?
TheTank

1
@ TheTank, y = x एक ही वस्तु को दो नामों (संदर्भों) को संदर्भित करता है, अर्थात "y x है" सत्य है। X के माध्यम से वस्तु पर किया गया कोई भी परिवर्तन y के माध्यम से समान परिवर्तन के बराबर है। हालाँकि, u, v, w नई अलग-अलग वस्तुओं के संदर्भ हैं, जो कि तात्कालिकता के दौरान x से कॉपी किए गए मान हैं। U, v (उथली प्रति) और w (डीपकोपी) के बीच के अंतर के लिए, कृपया docs.python.org/2/library/copy.html
gpanda

63

अजगर 3.5+ पर ** अनपैकिंग ऑपरेटर का उपयोग करके उथले प्रतिलिपि प्राप्त करने का एक आसान तरीका है। पेप 448 द्वारा परिभाषित ।

>>>dict1 = {"key1": "value1", "key2": "value2"}
>>>dict2 = {**dict1}
>>>print(dict2)
{'key1': 'value1', 'key2': 'value2'}
>>>dict2["key2"] = "WHY?!"
>>>print(dict1)
{'key1': 'value1', 'key2': 'value2'}
>>>print(dict2)
{'key1': 'value1', 'key2': 'WHY?!'}

** शब्दकोश को एक नए शब्दकोश में खोल देता है जिसे बाद में डिक्ट 2 को सौंपा जाता है।

हम यह भी पुष्टि कर सकते हैं कि प्रत्येक शब्दकोश में एक अलग आईडी है।

>>>id(dict1)
 178192816

>>>id(dict2)
 178192600

यदि एक गहरी प्रतिलिपि की आवश्यकता है तो copy.deepcopy () अभी भी जाने का रास्ता है।


3
यह सी ++ में संकेत की तरह भयानक दिखता है। कार्य पूरा करने के लिए अच्छा है, लेकिन पठनीयता बुद्धिमान मैं इस प्रकार के ऑपरेटरों को नापसंद करता हूं।
अर्नेस्टो

1
इसमें एक तरह का c'ish लुक होता है ... लेकिन कई डिक्शनरी को एक साथ मर्ज करने पर, सिंटैक्स बहुत स्मूथ दिखता है।
पाबटोर

2
इसके साथ सावधान रहें, यह केवल एक उथले प्रति प्रदर्शन करता है।
सेबेस्टियन ड्रेसर

आप सही हैं @SebastianDressler, मैं समायोजन समायोजित करूँगा। thnx।
पाबोररे

2
उपयोगी अगर आप कुछ स्पिरिट के साथ कॉपी बनाना चाहते हैं:dict2 = {**dict1, 'key3':'value3'}
evg656e

47

पायथन 2.7 और 3 दोनों में एक तानाशाह की प्रतिलिपि बनाने के लिए सबसे अच्छा और सबसे आसान तरीका है ...

सरल (एकल-स्तरीय) शब्दकोश की एक प्रति बनाने के लिए:

1. मौजूदा तानाशाह की ओर इशारा करने वाले संदर्भ को उत्पन्न करने के बजाय, तानाशाही () पद्धति का उपयोग करना ।

my_dict1 = dict()
my_dict1["message"] = "Hello Python"
print(my_dict1)  # {'message':'Hello Python'}

my_dict2 = dict(my_dict1)
print(my_dict2)  # {'message':'Hello Python'}

# Made changes in my_dict1 
my_dict1["name"] = "Emrit"
print(my_dict1)  # {'message':'Hello Python', 'name' : 'Emrit'}
print(my_dict2)  # {'message':'Hello Python'}

2. अंतर्निहित अद्यतन () पायथन शब्दकोश की विधि का उपयोग करना ।

my_dict2 = dict()
my_dict2.update(my_dict1)
print(my_dict2)  # {'message':'Hello Python'}

# Made changes in my_dict1 
my_dict1["name"] = "Emrit"
print(my_dict1)  # {'message':'Hello Python', 'name' : 'Emrit'}
print(my_dict2)  # {'message':'Hello Python'}

नेस्टेड या जटिल शब्दकोश की एक प्रति बनाने के लिए:

अंतर्निहित प्रतिलिपि मॉड्यूल का उपयोग करें , जो एक सामान्य उथले और गहरी प्रतिलिपि संचालन प्रदान करता है। यह मॉड्यूल पायथन 2.7 और 3. * दोनों में मौजूद है

import copy

my_dict2 = copy.deepcopy(my_dict1)

6
मेरा मानना dict()है कि उथली प्रतिलिपि एक गहरी प्रति नहीं है। मतलब कि यदि आपके पास एक नेस्टेड है, dictतो बाहरी dictएक प्रति होगी, लेकिन आंतरिक ताना मूल आंतरिक ताना के लिए एक संदर्भ होगा।
शमूएल

@ शमूएल हाँ, ये दोनों विधियाँ एक उथली प्रतिलिपि बनाएँगी, गहरी नहीं। देखिए, अपडेटेड जवाब।
एके निराला

37

आप एक शब्दकोश की समझ के साथ एक नया शब्दकोश भी बना सकते हैं। यह कॉपी आयात करने से बचता है।

dout = dict((k,v) for k,v in mydict.items())

निश्चित रूप से अजगर में = = 2.7 आप कर सकते हैं:

dout = {k:v for k,v in mydict.items()}

लेकिन बैकवर्ड कंप्टर्स के लिए, टॉप मेथड बेहतर है।


4
यह विशेष रूप से उपयोगी है यदि आप अधिक नियंत्रण चाहते हैं कि कैसे और क्या वास्तव में नकल की जाती है। +1
ApproachingDarknessFish

14
ध्यान दें कि यह विधि एक गहरी प्रतिलिपि निष्पादित नहीं करती है, और यदि आप उथली प्रतिलिपि चाहते हैं, जिसकी प्रतिलिपि बनाने के लिए कुंजियों पर नियंत्रण की d2 = dict.copy(d1)आवश्यकता नहीं है , तो किसी भी आयात की आवश्यकता नहीं है।
जेरेक पिओर्कोव्स्की

1
@ JarekPiórkowski: या आप एक विधि को एक विधि कह सकते हैं:d2 = d1.copy()
अज़ात इब्रकोव

ध्यान दें कि आपको पहले उदाहरण में समझने की आवश्यकता नहीं है। dict.itemsपहले से ही एक कुंजी / मान जोड़ी पुनरावृत्ति देता है। तो आप बस उपयोग कर सकते हैं dict(mydict.items())(आप भी उपयोग कर सकते हैं dict(mydict))। यदि आप प्रविष्टियों को फ़िल्टर करना चाहते हैं तो समझ में आना उपयोगी हो सकता है।
पॉल रूनी

22

अन्य प्रदान किए गए समाधानों के अलावा, आप **शब्दकोश को एक खाली शब्दकोश में एकीकृत करने के लिए उपयोग कर सकते हैं , जैसे,

shallow_copy_of_other_dict = {**other_dict}

अब आपके पास "उथली" प्रति होगी other_dict

अपने उदाहरण के लिए लागू:

>>> dict1 = {"key1": "value1", "key2": "value2"}
>>> dict2 = {**dict1}
>>> dict2
{'key1': 'value1', 'key2': 'value2'}
>>> dict2["key2"] = "WHY?!"
>>> dict1
{'key1': 'value1', 'key2': 'value2'}
>>>

सूचक: उथले और गहरे कॉपियों के बीच अंतर


1
इसका परिणाम उथली प्रति है, गहरी प्रति नहीं।
बजे sytech

1
मैं यह कोशिश कर रहा था लेकिन परेशानी हो रही थी। यह केवल अजगर 3.5 और ऊपर के लिए काम करता है। python.org/dev/peps/pep-0448
ThatGuyRob

19

पायथन में असाइनमेंट स्टेटमेंट ऑब्जेक्ट्स की प्रतिलिपि नहीं बनाते हैं, वे लक्ष्य और ऑब्जेक्ट के बीच बाइंडिंग बनाते हैं।

इसलिए, dict2 = dict1यह dict2उस वस्तु के बीच एक और बाध्यकारी परिणाम देता है जो dict1संदर्भित करता है।

यदि आप एक हुक कॉपी करना चाहते हैं, तो आप उपयोग कर सकते हैं copy module। प्रतिलिपि मॉड्यूल में दो इंटरफ़ेस हैं:

copy.copy(x)
Return a shallow copy of x.

copy.deepcopy(x)
Return a deep copy of x.

उथली और गहरी नकल के बीच का अंतर केवल यौगिक वस्तुओं के लिए प्रासंगिक है (ऐसी वस्तुएं जिनमें अन्य वस्तुएं होती हैं, जैसे सूची या वर्ग उदाहरण):

एक उथले प्रति एक नया परिसर वस्तु और फिर वस्तुओं के लिए इसे में संदर्भ मूल में पाया सम्मिलित करता है (जहां तक संभव हो) निर्माण करती है।

एक गहरी प्रतिलिपि एक नई यौगिक वस्तु का निर्माण करती है और फिर, पुनरावृत्ति करती है, मूल में पाई जाने वाली वस्तुओं में प्रतियों को सम्मिलित करती है।

उदाहरण के लिए, अजगर 2.7.9 में:

>>> import copy
>>> a = [1,2,3,4,['a', 'b']]
>>> b = a
>>> c = copy.copy(a)
>>> d = copy.deepcopy(a)
>>> a.append(5)
>>> a[4].append('c')

और परिणाम है:

>>> a
[1, 2, 3, 4, ['a', 'b', 'c'], 5]
>>> b
[1, 2, 3, 4, ['a', 'b', 'c'], 5]
>>> c
[1, 2, 3, 4, ['a', 'b', 'c']]
>>> d
[1, 2, 3, 4, ['a', 'b']]

10

आप dictनिर्माणकर्ता को अतिरिक्त कीवर्ड तर्क के साथ कॉल करके एक बार में नवनिर्मित कॉपी को कॉपी और संपादित कर सकते हैं :

>>> dict1 = {"key1": "value1", "key2": "value2"}
>>> dict2 = dict(dict1, key2="WHY?!")
>>> dict1
{'key2': 'value2', 'key1': 'value1'}
>>> dict2
{'key2': 'WHY?!', 'key1': 'value1'}

9

इसने मुझे भी भ्रमित कर दिया, शुरू में, क्योंकि मैं सी पृष्ठभूमि से आ रहा था।

सी में, एक चर एक परिभाषित प्रकार के साथ स्मृति में एक स्थान है। एक चर के लिए असाइन करना डेटा को चर की स्मृति स्थान में कॉपी करता है।

लेकिन पायथन में, चर वस्तुओं की तरह संकेत करते हैं। इसलिए एक वेरिएबल को दूसरे को असाइन करने से कॉपी नहीं बनती है, यह सिर्फ उस वैरिएबल नेम को उसी ऑब्जेक्ट की ओर इशारा करता है।


5
अजगर चर अधिक सी + + संदर्भ की तरह काम करते हैं
रग्गरो तुर्रा

7
क्योंकि अजगर में सब कुछ एक वस्तु है! diveintopython.net/getting_to_know_python/… (हाँ, यह प्रतिक्रिया कई साल देर से है, लेकिन शायद यह किसी के लिए कुछ उपयोग की है!)
ग्रिमैन

1
मेरा मानना ​​है कि पायथन भाषा के शब्दार्थ कहते हैं कि "चर" नहीं हैं। उन्हें "नामित संदर्भ" कहा जाता है; एक वस्तु के संदर्भ कोड में एक वाक्यविन्यास स्ट्रिंग है। किसी वस्तु के कई नाम हो सकते हैं। अपरिवर्तनीय वस्तुएं जैसे कि इन्टस और फ्लोट्स और स्ट्रैट इंस्टेंस इसकी प्रति प्रक्रिया का केवल एक उदाहरण है। स्मृति में 1 का एक int एक ही मेमोरी पते पर 2 या कुछ अन्य मान में परिवर्तित नहीं होता है जब आप यह myvalue = 1 myvalue = 2 करते हैं
DevPlayer

7

अजगर में हर चर (जैसे सामान dict1या strया __builtins__मशीन के अंदर कुछ छिपा आदर्शवादी "वस्तु" के लिए सूचक है।

यदि आप सेट करते हैं dict1 = dict2, तो आप बस dict1उसी ऑब्जेक्ट (या मेमोरी लोकेशन, या जो भी सादृश्य पसंद करते हैं) को इंगित करते हैं dict2। अब, जिस ऑब्जेक्ट को संदर्भित किया dict1जाता है, वही ऑब्जेक्ट द्वारा संदर्भित होता है dict2

आप देख सकते हैं: dict1 is dict2होना चाहिए True। साथ ही, id(dict1)जैसा होना चाहिए वैसा ही होना चाहिए id(dict2)

आप चाहते हैं dict1 = copy(dict2), या dict1 = deepcopy(dict2)

copyऔर के बीच का अंतर deepcopy? deepcopyयह सुनिश्चित कर लेगा कि किन तत्वों dict2(क्या आपने इसे किसी सूची में इंगित किया है?) भी प्रतियां हैं।

मैं deepcopyज्यादा उपयोग नहीं करता - यह आमतौर पर कोड लिखने की खराब प्रथा है जो इसकी आवश्यकता है (मेरी राय में)।


मुझे बस एहसास हुआ कि मुझे हमेशा डीकोस्कोपी का उपयोग करने की आवश्यकता है ताकि जब मैं एक नेस्टेड शब्दकोश की प्रतिलिपि बनाऊं और नेस्टेड प्रविष्टियों को संशोधित करना शुरू करूं, तो प्रभाव केवल कॉपी पर होता है और मूल नहीं।
flutefreak7

6

dict1एक प्रतीक है जो एक अंतर्निहित शब्दकोश वस्तु का संदर्भ देता है। केवल उसी संदर्भ dict1को निर्दिष्ट करने के लिए असाइन करना dict2dict2प्रतीक के माध्यम से एक कुंजी के मूल्य को बदलने से अंतर्निहित वस्तु बदल जाती है, जो प्रभावित भी करती है dict1। यह भ्रामक है।

संदर्भों से अपरिवर्तनीय मूल्यों के बारे में तर्क करना बहुत आसान है, इसलिए जब भी संभव हो प्रतियां बनाएं:

person = {'name': 'Mary', 'age': 25}
one_year_later = {**person, 'age': 26}  # does not mutate person dict

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

one_year_later = dict(person, age=26)

5

dict2 = dict1शब्दकोश की नकल नहीं करता है। यह उसी प्रोग्राम dict2को संदर्भित करने के लिए आपको प्रोग्रामर को दूसरा तरीका ( ) देता है।


5
>>> dict2 = dict1
# dict2 is bind to the same Dict object which binds to dict1, so if you modify dict2, you will modify the dict1

डिक्ट ऑब्जेक्ट को कॉपी करने के कई तरीके हैं, मैं बस उपयोग करता हूं

dict_1 = {
           'a':1,
           'b':2
         }
dict_2 = {}
dict_2.update(dict_1)

12
dict_2 = dict_1.copy()बहुत अधिक कुशल और तार्किक है।
जीन-फ्रांस्वा फाबरे

2
ध्यान दें कि यदि आपके पास dict1 के अंदर एक तानाशाही है, तो_1_1 के साथ। () आप जो परिवर्तन आप डिक्टेन में कर रहे हैं वह डिक्टा .2 में भी होता है। इस स्थिति में आपको इसके बजाय copy.deepcopy (dict_1) का उपयोग करना चाहिए।
19

1

जैसा कि दूसरों ने समझाया है, बिल्ट-इन dictवह नहीं करता है जो आप चाहते हैं। लेकिन पाइथन 2 (और शायद 3 भी) में आप आसानी से एक ऐसी ValueDictक्लास बना सकते हैं, जिसकी कॉपी =आप सुनिश्चित कर सकते हैं कि मूल नहीं बदलेगा।

class ValueDict(dict):

    def __ilshift__(self, args):
        result = ValueDict(self)
        if isinstance(args, dict):
            dict.update(result, args)
        else:
            dict.__setitem__(result, *args)
        return result # Pythonic LVALUE modification

    def __irshift__(self, args):
        result = ValueDict(self)
        dict.__delitem__(result, args)
        return result # Pythonic LVALUE modification

    def __setitem__(self, k, v):
        raise AttributeError, \
            "Use \"value_dict<<='%s', ...\" instead of \"d[%s] = ...\"" % (k,k)

    def __delitem__(self, k):
        raise AttributeError, \
            "Use \"value_dict>>='%s'\" instead of \"del d[%s]" % (k,k)

    def update(self, d2):
        raise AttributeError, \
            "Use \"value_dict<<=dict2\" instead of \"value_dict.update(dict2)\""


# test
d = ValueDict()

d <<='apples', 5
d <<='pears', 8
print "d =", d

e = d
e <<='bananas', 1
print "e =", e
print "d =", d

d >>='pears'
print "d =", d
d <<={'blueberries': 2, 'watermelons': 315}
print "d =", d
print "e =", e
print "e['bananas'] =", e['bananas']


# result
d = {'apples': 5, 'pears': 8}
e = {'apples': 5, 'pears': 8, 'bananas': 1}
d = {'apples': 5, 'pears': 8}
d = {'apples': 5}
d = {'watermelons': 315, 'blueberries': 2, 'apples': 5}
e = {'apples': 5, 'pears': 8, 'bananas': 1}
e['bananas'] = 1

# e[0]=3
# would give:
# AttributeError: Use "value_dict<<='0', ..." instead of "d[0] = ..."

कृपया यहां चर्चा की गई लैवल्यू मॉडिफिकेशन पैटर्न का संदर्भ लें: पायथन 2.7 - लैवल संशोधन के लिए स्वच्छ वाक्यविन्यास । कुंजी अवलोकन है कि है strऔर intअजगर में मूल्यों के रूप में व्यवहार करते हैं (भले ही वे वास्तव में हुड के नीचे अपरिवर्तनीय वस्तुओं रहे हैं)। जब आप यह देख रहे हैं, तो कृपया यह भी देखें कि कुछ भी जादुई रूप से विशेष नहीं है strया intdictएक ही तरह से इस्तेमाल किया जा सकता है, और मैं कई मामलों के बारे में सोच सकता हूं जहां ValueDictसमझ में आता है।


0

निम्नलिखित कोड, जो कि dicts पर है, जो कि jsc सिंटैक्स का अनुसरण करता है डीपकोपी की तुलना में 3 गुना अधिक तेज है

def CopyDict(dSrc):
    try:
        return json.loads(json.dumps(dSrc))
    except Exception as e:
        Logger.warning("Can't copy dict the preferred way:"+str(dSrc))
        return deepcopy(dSrc)

0

मैं एक अजीब व्यवहार में भाग गया जब कक्षा w / o की गहरी प्रतिलिपि शब्दकोश संपत्ति की कोशिश कर रहा था, इसे चर को असाइन करना

new = copy.deepcopy(my_class.a)काम नहीं करता है अर्थात संशोधित newकरता हैmy_class.a

लेकिन अगर आप करते हैं old = my_class.aऔर फिर new = copy.deepcopy(old)यह पूरी तरह से काम करता है यानी संशोधित newकरना प्रभावित नहीं करता हैmy_class.a

मुझे यकीन नहीं है कि ऐसा क्यों होता है, लेकिन आशा है कि यह कुछ घंटे बचाने में मदद करता है! :)


तो तुम कैसे की एक गहरी प्रतिलिपि बनाते हैं my_class.a?
एंथनी

सबसे अच्छा तरीका नहीं है। अच्छा रिस्पांस है बोल्ड।
डेविड बीउचेमिन

-1

क्योंकि, dict2 = ताना 1, तानाशाही 2 तानाशाही का संदर्भ रखता है। स्मृति में तानाशाही और तानाशाही दोनों एक ही स्थान की ओर इशारा करते हैं। अजगर में उत्परिवर्तित वस्तुओं के साथ काम करते समय यह सिर्फ एक सामान्य मामला है। जब आप अजगर में उत्परिवर्तनीय वस्तुओं के साथ काम कर रहे हैं तो आपको सावधान रहना चाहिए क्योंकि यह डिबग करना कठिन है। जैसे कि निम्न उदाहरण।

 my_users = {
        'ids':[1,2],
        'blocked_ids':[5,6,7]
 }
 ids = my_users.get('ids')
 ids.extend(my_users.get('blocked_ids')) #all_ids
 print ids#output:[1, 2, 5, 6, 7]
 print my_users #output:{'blocked_ids': [5, 6, 7], 'ids': [1, 2, 5, 6, 7]}

यह उदाहरण इरादा अवरुद्ध आईडी सहित सभी उपयोगकर्ता आईडी प्राप्त करना है। हमें आईडी वेरिएबल से मिला है, लेकिन हमने अनायास ही my_users का मान भी अपडेट कर दिया है । जब आप बढ़ाया आईडी के साथ blocked_ids my_users अपडेट किए गए हैं क्योंकि आईडी का उल्लेख my_users


-1

लूप के लिए उपयोग करके प्रतिलिपि बनाई जा रही है:

orig = {"X2": 674.5, "X3": 245.0}

copy = {}
for key in orig:
    copy[key] = orig[key]

print(orig) # {'X2': 674.5, 'X3': 245.0}
print(copy) # {'X2': 674.5, 'X3': 245.0}
copy["X2"] = 808
print(orig) # {'X2': 674.5, 'X3': 245.0}
print(copy) # {'X2': 808, 'X3': 245.0}

1
यह केवल सरल शब्दकोशों के लिए काम करता है। उपयोग क्यों नहीं deepcopyकिया जाता है, जो इस उद्देश्य के लिए स्पष्ट रूप से बनाया गया है?
एंथनी

सबसे अच्छा तरीका नहीं है। अच्छा रिस्पांस है बोल्ड।
डेविड बीउचेमिन

-6

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

dict2 = eval(repr(dict1))

जहां ऑब्जेक्ट ताना 2 डिक्टेड 1 की एक स्वतंत्र प्रति है, इसलिए आप डिक्टा 1 को प्रभावित किए बिना तानाशाही को संशोधित कर सकते हैं।

यह किसी भी प्रकार की वस्तु के लिए काम करता है।


4
यह उत्तर गलत है, और इसका उपयोग नहीं किया जाना चाहिए। एक उपयोगकर्ता-परिभाषित वर्ग, उदाहरण के लिए, हो सकता है कि उपयुक्त __repr__को फिर से निकाला जाए, और न ही ऑब्जेक्ट की कक्षा को वर्तमान दायरे में कहा जाए। यहां तक ​​कि बिल्ट-इन प्रकारों के साथ चिपके रहते हैं, यह विफल हो जाएगा यदि एक ही वस्तु को कई कुंजी के तहत संग्रहीत किया जाता है, dict2तो फिर दो अलग-अलग ऑब्जेक्ट होंगे। एक सेल्फ रेफ़रेंशियल डिक्शनरी, dict1जिसमें स्वयं शामिल है, के बजाय समाहित होगी Ellipsis। इसका उपयोग करना बेहतर होगाdict1.copy()
एल्ड्रिच चीज़

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