কীভাবে একটি অভিধান অনুলিপি করবেন এবং কেবল অনুলিপিটি সম্পাদনা করুন


852

কেউ আমাকে এই ব্যাখ্যা করুন পারি? এটি আমার কোনও অর্থবোধ করে না।

আমি অন্য অভিধানে একটি কপি অনুলিপি করি এবং দ্বিতীয়টি সম্পাদনা করি এবং উভয়ই পরিবর্তিত হয়। ইহা কি জন্য ঘটিতেছে?

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

3
পাইথন রেফারেন্সটি কল্পনা করার জন্য পাইথনটিউটর দুর্দান্ত। শেষ পদক্ষেপে এই কোড এখানে । আপনি একই আদেশটি দেখতে dict1এবং dict2নির্দেশ করতে পারেন ।
wjandrea

উত্তর:


881

পাইথন কখনই স্পষ্টভাবে বস্তু অনুলিপি করে না। আপনি যখন সেট করেন dict2 = dict1, আপনি তাদেরকে একই হুবহু ডিক অবজেক্টটি উল্লেখ করছেন, সুতরাং আপনি যখন এটি পরিবর্তন করবেন, তখন এর সমস্ত উল্লেখগুলি তার বর্তমান অবস্থানে অবজেক্টটির উল্লেখ করে রাখে।

আপনি যদি ডিকটি অনুলিপি করতে চান (যা বিরল), আপনার সাথে এটি স্পষ্টভাবে করতে হবে

dict2 = dict(dict1)

অথবা

dict2 = dict1.copy()

26
"ডিক্ট 2 এবং ডিক্ট 1 একই অভিধানে নির্দেশ করুন" বলা ভাল , আপনি ডিক্ট 1 বা ডিক্ট 2 পরিবর্তন করছেন না তবে তারা কী বোঝায়।
গ্রে উইজার্ডেক্স

275
এছাড়াও নোট করুন যে ডিক্ট কপি () অগভীর, যদি কোনও নেস্টেড তালিকা / ইত্যাদি থাকে তবে উভয় ক্ষেত্রেই পরিবর্তনগুলি প্রয়োগ করা হবে। IIRC। ডিপকপি তা এড়াতে পারবে।
উইল

16
এটি একেবারেই সঠিক নয় যে পাইথন কখনও স্পষ্টভাবে বস্তু অনুলিপি করে না। প্রাথমিক তথ্য প্রকার যেমন ইনট, ফ্লোট এবং বুলকেও বস্তু হিসাবে বিবেচনা করা হয় (এটি dir(1)দেখতে কেবল কিছু করুন), তবে সেগুলি স্পষ্টভাবে অনুলিপি করা হয়।
ড্যানিয়েল কুল্ম্যান্ন

17
@ ড্যানিয়েলকুলম্যান, আমি মনে করি আপনি অন্যান্য ভাষাগুলি কীভাবে কাজ করেছেন তার উপর ভিত্তি করে পাইথন সম্পর্কে আপনার ভুল ধারণা থাকতে পারে। পাইথনে, ক) "আদিম ডেটা ধরণের" কোনও ধারণা নেই। int, floatএবং boolউদাহরণগুলি বাস্তব পাইথন অবজেক্টস এবং খ) এই ধরণের বস্তুগুলি স্পষ্টভাবে অনুলিপি করা হয় না যখন আপনি সেগুলি পাস করেন, নিশ্চিতভাবে সি अर्थিক পাইথন স্তরে নয় এবং সিপিথনের বাস্তবায়নের বিশদ হিসাবেও নয়।
মাইক গ্রাহাম

39
"ডিপ কপি ক্ষতিকারক হিসাবে বিবেচনা করা হয়" এর মতো অসমর্থিত বক্তব্য অসহযোগী। অন্য সমস্ত কিছু সমান, অগভীর একটি জটিল তথ্য কাঠামো অনুলিপি করা একই কাঠামোর গভীর অনুলিপি করার চেয়ে অপ্রত্যাশিত প্রান্তের সমস্যাগুলি উত্পন্ন করার সম্ভাবনা যথেষ্ট । যে অনুলিপিতে পরিবর্তনগুলি মূল বস্তুকে সংশোধন করে তা অনুলিপি নয়; এটি একটি বাগ অতএব, অধিকাংশ ব্যবহারের ক্ষেত্রে একেবারে উচিত কল copy.deepcopy()বদলে dict()বা dict.copy()ইমরান এর সংক্ষিপ্ত উত্তর এই উত্তর মতো মানসিক সুস্থতা ডান দিকে থাকে।
সিসিল কারি

645

আপনি যখন অর্পণ করেন dict2 = dict1, আপনি একটি অনুলিপি তৈরি করছেন না dict1, এটির dict2জন্য কেবল অন্য নাম হওয়ার ফলাফল dict1

অভিধান, ব্যবহার মত চপল ধরনের অনুলিপি করতে copy/ deepcopyএর copyমডিউল।

import copy

dict2 = copy.deepcopy(dict1)

80
আমি যে কোনও অভিধানের সাথে কাজ করি, ডিপকপিটি আমার যা প্রয়োজন তা ... আমি একটি বাগের কারণে বেশ কয়েক ঘন্টা হারিয়েছি কারণ এটি একটি নেস্টেড ডিকশনারিটির সম্পূর্ণ কপি পাচ্ছিলাম না এবং নেস্টেড এন্ট্রিগুলিতে আমার পরিবর্তনগুলি মূলটিকে প্রভাবিত করছে ।
flutefreak7

7
একই অবস্থা. ডিপকপি () কৌশলটি করে। আসল ঘটনাটির একটি 'অনুলিপি'তে টাইমস্ট্যাম্প যুক্ত করে ঘুরানো ক্যাশের অভ্যন্তরে আমার নেস্টেড ডিক্টসগুলিকে গণ্ডগোল করছে। ধন্যবাদ!
fxstein

8
এটি আসলে সঠিক উত্তর হিসাবে চিহ্নিত করা উচিত; এই উত্তরটি সাধারণ এবং এটি অভিধানের অভিধানের জন্যও কাজ করে।
ওরেজভানি

30
এটি গ্রহণযোগ্য উত্তর হওয়া উচিত। বর্তমান গৃহীত উত্তরের মন্তব্য বিভাগে নিঃশব্দ "ডিপ অনুলিপি ক্ষতিকারক হিসাবে বিবেচিত হয়" বাণীতে নেস্টেড ডিকশনারিগুলি (যেমন এখানে ডকুমেন্ট করা আছে) অনুলিপি করার সময় সুসংগতভাবে সংলগ্ন সমস্যাগুলিকে আমন্ত্রণ জানায় এবং এ জাতীয় হিসাবে চ্যালেঞ্জ জানানো উচিত।
সিসিল কারি

ডিপকপি একটি জটিল অভিধান কাঠামোর ক্ষেত্রে যাওয়ার উপায়। ডিক্ট কোড.কপি () কেবল কীগুলির মানগুলিকে রেফারেন্স হিসাবে এবং অনুলিপিকে হিসাবে অনুলিপি করে।
রোহিত এন

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 is x" সত্য is এক্স এর মাধ্যমে অবজেক্টে যে কোনও পরিবর্তন হ'ল y এর মাধ্যমে একই পরিবর্তনের সমতুল্য। তবে আপনি, ভি, ডব্লু হ'ল নতুন বিভিন্ন বস্তুর উল্লেখ যা ইনস্ট্যান্টেশনের সময় এক্স থেকে কপি করা মান। ইউ, ভি (অগভীর অনুলিপি) এবং ডাব্লু (ডিপকপি) এর মধ্যে পার্থক্য হিসাবে দয়া করে ডকস.পিথন.আর.
কপি

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

যদি একটি গভীর অনুলিপি প্রয়োজন হয় তবে অনুলিপি.দীপকপি () এখনও যাওয়ার উপায়।


3
এটি সি ++ এর পয়েন্টারের মতো ভয়ঙ্কর দেখাচ্ছে looks কাজটি সম্পাদন করার জন্য দুর্দান্ত, তবে পাঠযোগ্যতার ভিত্তিতে আমি এই ধরণের অপারেটরদের অপছন্দ করি।
আর্নেস্তো

1
এতে এক ধরণের সি'স লুক থাকে ... তবে একাধিক ডিকশনারি একত্রিত করার সময় সিনট্যাক্সটি বেশ মসৃণ লাগে।
পাবটোরে

2
এটির সাথে সতর্ক থাকুন, এটি কেবল অগভীর অনুলিপি সম্পাদন করে।
সেবাস্তিয়ান ড্রেসলার

আপনি ঠিক বলেছেন সেবাস্তিয়ানড্রেসার, আমি ম্যাকডে সমন্বয় করব। 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'}

২. পাইথন অভিধানের অন্তর্নির্মিত আপডেট () পদ্ধতি ব্যবহার করা।

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'}

নেস্টেড বা জটিল অভিধানের একটি অনুলিপি তৈরি করতে:

অন্তর্নির্মিত অনুলিপি মডিউলটি ব্যবহার করুন , যা জেনেরিক অগভীর এবং গভীর অনুলিপি ক্রিয়াকলাপ সরবরাহ করে। এই মডিউলটি পাইথন ২.7 এবং ৩ উভয় ক্ষেত্রে উপস্থিত রয়েছে *

import copy

my_dict2 = copy.deepcopy(my_dict1)

6
আমি বিশ্বাস করি যে dict()অগভীর অনুলিপি তৈরি করে একটি গভীর অনুলিপি নয়। মানে আপনার যদি নেস্ট থাকে dictতবে dictবাইরেরটি অনুলিপি হবে তবে অভ্যন্তরীণ ডিকটি মূল অভ্যন্তরীণ ডিক্টের একটি রেফারেন্স হবে।
শুক্র 15

@ শ্মুয়েলস হ্যাঁ, এই দুটি পদ্ধতিই অগভীর অনুলিপি তৈরি করবে, গভীর নয়। দেখুন, আপডেট উত্তর।
কে নিরালা

37

আপনি কেবল অভিধান বোঝার সাথে একটি নতুন অভিধান তৈরি করতে পারেন make এটি অনুলিপি আমদানি করা এড়িয়ে চলে।

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

অবশ্যই পাইথন> = 2.7 এ আপনি করতে পারেন:

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

পিছনের দিকের কম্পাটের জন্য, শীর্ষ পদ্ধতিটি আরও ভাল is


4
আপনি কীভাবে এবং কীভাবে অনুলিপি করা হয়েছে তার উপর যদি আরও নিয়ন্ত্রণ চান তবে এটি বিশেষত কার্যকর। +1 টি
ApproachingDarknessFish

14
নোট করুন যে এই পদ্ধতিটি একটি গভীর অনুলিপি সম্পাদন করে না, এবং যদি আপনি অনুলিপি অনুলিপি চাবি অনুলিপি করতে চাবি নিয়ন্ত্রণ d2 = dict.copy(d1)করতে প্রয়োজন হয় না , তবে কোনও আমদানি প্রয়োজন হয় না।
জেরেক পাইর্কোভস্কি

1
@ জারেকপিয়ারকোভস্কি: বা আপনি কোনও পদ্ধতির মতো কোনও পদ্ধতিতে কল করতে পারেন:d2 = d1.copy()
আজাত ইব্রাকোভ

মনে রাখবেন যে প্রথম উদাহরণে আপনার বোঝার দরকার নেই। dict.itemsইতিমধ্যে একটি কী / মান জোড়া পুনরাবৃত্তিযোগ্য returns সুতরাং আপনি কেবল ব্যবহার করতে পারেন 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.

অগভীর এবং গভীর অনুলিপিটির মধ্যে পার্থক্য কেবল যৌগিক অবজেক্টের জন্যই প্রাসঙ্গিক (যে বস্তুগুলিতে অন্যান্য বস্তু যেমন তালিকা বা শ্রেণীর উদাহরণ রয়েছে):

একটি অগভীর অনুলিপি একটি নতুন যৌগিক বস্তু তৈরি করে এবং তারপরে (সম্ভাব্য পরিমাণে) মূলটিতে পাওয়া বস্তুগুলির মধ্যে রেফারেন্স সন্নিবেশ করায়।

একটি গভীর অনুলিপি একটি নতুন যৌগিক বস্তু তৈরি করে এবং তারপরে, পুনরাবৃত্তভাবে, মূলটিতে পাওয়া সামগ্রীর মধ্যে অনুলিপি সন্নিবেশ করায়।

উদাহরণস্বরূপ, পাইথনে ২.7.৯:

>>> 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 মাইভ্যালু = 2 করেন
মেমরির

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
দ্রষ্টব্য যে আপনার ডিক্ট 1 এর ভিতরে ডিক থাকলে ডিক_1 কোপি () এর মাধ্যমে আপনি ডিক্ট 3-তে অভ্যন্তরীণ ডিকের উপর যে পরিবর্তনগুলি করেন সেগুলিও ডিক_1 এর অভ্যন্তরীণ ডিকের সাথে প্রয়োগ করা হয়। এই ক্ষেত্রে আপনার পরিবর্তে অনুলিপি.দীপকপি (ডিক_1) ব্যবহার করা উচিত।
কুইউজ

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] = ..."

: Lvalue পরিমার্জন প্যাটার্ন এখানে আলোচনা পড়ুন দয়া করে lvalue পরিবর্তনের পরিষ্কার সিনট্যাক্স - পাইথন 2.7 । কী পর্যবেক্ষণ করে strএবং intপাইথন মান যেমন আচরণ (যদিও তারা আসলে ফণা অধীন অপরিবর্তনীয় বস্তু করছি)। আপনি এটি পর্যবেক্ষণ করার সময়, দয়া করে এটিও পর্যবেক্ষণ করুন যে কিছুই জাদুগতভাবে বিশেষ strবা কিছু নয় intdictঅনেক একই উপায়ে ব্যবহার করা যেতে পারে এবং আমি এমন অনেকগুলি ক্ষেত্রে ভাবতে পারি যেখানে ValueDictঅর্থবোধ হয়।


0

নিম্নলিখিত কোডটি, যা ডিক্টসে রয়েছে যা ডিপকপির চেয়ে জসন সিনট্যাক্স অনুসরণ করে 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

ক্লাস ডাব্লু / ও এর ভেরিয়েবলের নিয়োগের ক্ষেত্রে অভিধানের গভীর সম্পত্তি কপিরাইট করার চেষ্টা করার সময় আমি একটি অদ্ভুত আচরণে চলে এসেছি

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

কারণ, ডিক্ট 2 = ডিক্ট 1, ডিক্ট 2 এর সাথে ডেট 1 এর রেফারেন্স রয়েছে। ডিকট 1 এবং ডিক্ট 2 উভয়ই স্মৃতিতে একই অবস্থানকে নির্দেশ করে। অজগরটিতে পরিবর্তনীয় বস্তুর সাথে কাজ করার সময় এটি কেবল একটি সাধারণ ঘটনা। আপনি যখন অজগরে পরিবর্তনীয় বস্তুর সাথে কাজ করছেন তখন আপনার অবশ্যই যত্নবান হওয়া উচিত কারণ এটি ডিবাগ করা শক্ত hard যেমন নীচের উদাহরণ হিসাবে।

 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]}

এই উদাহরণের উদ্দেশ্যটি হ'ল অবরুদ্ধ আইডিসহ সমস্ত ব্যবহারকারী আইডি। যেটি আমরা আইডির ভেরিয়েবল থেকে পেয়েছি কিন্তু আমরা অজ্ঞাতসারে মাই_উসারদের মানও আপডেট করেছি । যখন আপনি বাড়ানো আইডি দিয়ে 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 কে প্রভাবিত না করে ডিক 2 সংশোধন করতে পারেন।

এটি কোনও ধরণের অবজেক্টের জন্য কাজ করে।


4
এই উত্তরটি ভুল, এবং ব্যবহার করা উচিত নয়। উদাহরণস্বরূপ, একটি ব্যবহারকারী-সংজ্ঞায়িত শ্রেণীর কাছে __repr__ইওল দ্বারা পুনর্গঠন করার উপযুক্ত নাও হতে পারে, না অবজেক্টের শ্রেণিটি বর্তমান স্কোপটিতে ডাকা হতে পারে। এমনকি অন্তর্নির্মিত ধরণের সাথে স্টিক করা, এটি ব্যর্থ হবে যদি একই বস্তুটি একাধিক কীতে সংরক্ষণ করা হয়, যেমন dict2দুটি পৃথক বস্তু থাকে। একটি স্ব-রেফারেন্সিয়াল অভিধান, যেখানে dict1নিজেই থাকে, পরিবর্তে এটি ধারণ করে Ellipsis। এটি ব্যবহার করা ভাল হবেdict1.copy()
এল্ড্রিচ চিজ

অবজেক্টস (বা "মান") সর্বদা চরিত্রের স্ট্রিংগুলির দ্বারা বিশ্বস্ত উপস্থাপনের প্রত্যাশা করা হয় না, কোনও পরিস্থিতিতে সাধারণ মানুষের পাঠযোগ্য উপায়ে নয়।
আলেক্সি
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.