অজগরে একটি ডিকের গভীর অনুলিপি


341

আমি dictপাইথনের একটি গভীর কপি তৈরি করতে চাই । দুর্ভাগ্যক্রমে এই .deepcopy()পদ্ধতির জন্য নেই dict। আমি কেমন করে ঐটি করি?

>>> my_dict = {'a': [1, 2, 3], 'b': [4, 5, 6]}
>>> my_copy = my_dict.deepcopy()
Traceback (most recent calll last):
  File "<stdin>", line 1, in <module>
AttributeError: 'dict' object has no attribute 'deepcopy'
>>> my_copy = my_dict.copy()
>>> my_dict['a'][2] = 7
>>> my_copy['a'][2]
7

শেষ লাইন হওয়া উচিত 3

আমি চাই যে পরিবর্তনগুলি my_dictস্ন্যাপশটের উপর প্রভাব ফেলবে না my_copy

আমি কেমন করে ঐটি করি? সমাধানটি পাইথন 3.x এর সাথে সামঞ্জস্যপূর্ণ হওয়া উচিত।


3
এটি কোনও সদৃশ কিনা তা আমি জানি না, তবে এটি: স্ট্যাকওভারফ্লো / প্রশ্নগুলি / 8৮৮64৪২ / প্যাথন-অভিধান অভিধান -ডিপিপিটি ভীষণ কাছাকাছি।
চার্লসপার্কার

উত্তর:


473

কেমন:

import copy
d = { ... }
d2 = copy.deepcopy(d)

পাইথন 2 বা 3:

Python 3.2 (r32:88445, Feb 20 2011, 21:30:00) [MSC v.1500 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import copy
>>> my_dict = {'a': [1, 2, 3], 'b': [4, 5, 6]}
>>> my_copy = copy.deepcopy(my_dict)
>>> my_dict['a'][2] = 7
>>> my_copy['a'][2]
3
>>>

16
প্রকৃতপক্ষে এটি আমি দেওয়া ওভারসিম্প্লিফাইড উদাহরণের জন্য কাজ করে। আমার কীগুলি সংখ্যা নয় তবে অবজেক্ট। যদি আমি অনুলিপি মডিউল ডকুমেন্টেশন পড়ি, কীগুলির জন্য আমাকে একটি __copy __ () / __ ডিপকপি __ () পদ্ধতি ঘোষণা করতে হবে। সেখানে আমাকে নেতৃত্ব দেওয়ার জন্য আপনাকে অনেক ধন্যবাদ!
অলিভিয়ার গ্রাগোয়ার

3
পাইথন 3.2 এবং 2.7 কোডগুলিতে কি কোনও পার্থক্য রয়েছে? এগুলি আমার কাছে অভিন্ন বলে মনে হচ্ছে। যদি তা হয় তবে কোডের একটি একক ব্লক এবং একটি বিবৃতি "পাইথন 3 এবং 2 উভয়ের জন্যই কাজ করে" এর চেয়ে ভাল হবে
মাস্ট্রলিয়ন

30
এটি উল্লেখ করার মতো copy.deepcopyবিষয় থ্রেড নিরাপদ নয়। এই কঠিন উপায় শিখেছি। অন্যদিকে, আপনার ব্যবহার কেস উপর নির্ভর করে, json.loads(json.dumps(d)) হয় থ্রেড নিরাপদ, এবং ভাল কাজ করে।
ছিনিয়ে নিন

1
@ আরব আপনার এই মন্তব্যটি উত্তর হিসাবে পোস্ট করা উচিত। এটি একটি কার্যকর বিকল্প। থ্রেড সুরক্ষা উপমা একটি গুরুত্বপূর্ণ পার্থক্য।
বুভিন জে

3
@ বুভিনজে সমস্যাটি হ'ল json.loadsপাইথনের dictবৈশিষ্ট্যগুলি JSON সিরিয়ালযোগ্য নয় এমন সমস্ত ব্যবহারের ক্ষেত্রে সমস্যার সমাধান হয় না। উদাহরণস্বরূপ একটি এপিআই থেকে যারা কেবল সাধারণ ডেটা স্ট্রাকচার নিয়ে কাজ করে তাদেরকে এটি সহায়তা করতে পারে, তবে আমি মনে করি না যে ওপি-র প্রশ্নের পুরোপুরি উত্তর দেওয়ার পক্ষে এটি যথেষ্ট পরিমাণ সমাধানের সমাধান।
24:37

36

ডিক্টকপি () অভিধান
আইডির জন্য অগভীর অনুলিপি ফাংশন অন্তর্নির্মিত ফাংশন যা আপনাকে ভেরিয়েবলের ঠিকানা দেয়

প্রথমে আপনার বুঝতে হবে "এই বিশেষ সমস্যাটি কেন হচ্ছে?"

In [1]: my_dict = {'a': [1, 2, 3], 'b': [4, 5, 6]}

In [2]: my_copy = my_dict.copy()

In [3]: id(my_dict)
Out[3]: 140190444167808

In [4]: id(my_copy)
Out[4]: 140190444170328

In [5]: id(my_copy['a'])
Out[5]: 140190444024104

In [6]: id(my_dict['a'])
Out[6]: 140190444024104

'এ' কী এর জন্য উভয় ডিসিকেটে উপস্থিত তালিকার ঠিকানা একই অবস্থানকে নির্দেশ করছে।
অতএব আপনি যখন আমার_ডিক্টে তালিকার মান পরিবর্তন করেন, তখন আমার_কপির তালিকাটিও পরিবর্তন হয়।


প্রশ্নে উল্লিখিত ডেটা কাঠামোর সমাধান:

In [7]: my_copy = {key: value[:] for key, value in my_dict.items()}

In [8]: id(my_copy['a'])
Out[8]: 140190444024176

অথবা আপনি উপরে বর্ণিত হিসাবে ডিপকপি ব্যবহার করতে পারেন।


4
আপনার সমাধান নেস্টেড অভিধানের জন্য কাজ করে না। ডিপকপি সেই কারণে পছন্দনীয়।
চার্লস প্লাগার

2
@ চার্লসপ্লেজার সম্মত! তবে আপনার এটিও লক্ষ্য করা উচিত যে তালিকার টুকরো টুকরো টুকরো করে কাজ করে না value[:]। সমাধানটি সর্বজনীন সমাধানের পরিবর্তে প্রশ্নে উল্লিখিত নির্দিষ্ট ডেটা কাঠামোর জন্য ছিল।
দ্য ব্যাজি কোডার

17

পাইথন 3.x

অনুলিপি ডিপকপি থেকে

my_dict = {'one': 1, 'two': 2}
new_dict_deepcopy = deepcopy(my_dict)

ডিপকপি ছাড়া আমি আমার ডোমেন অভিধানের মধ্যে থেকে হোস্টনাম অভিধানটি সরাতে অক্ষম।

ডিপকপি ছাড়াই আমি নিম্নলিখিত ত্রুটিটি পেয়েছি:

"RuntimeError: dictionary changed size during iteration"

... যখন আমি অন্য অভিধানের ভিতরে আমার অভিধান থেকে পছন্দসই উপাদানটি সরিয়ে দেওয়ার চেষ্টা করি।

import socket
import xml.etree.ElementTree as ET
from copy import deepcopy

ডোমেন একটি অভিধান অবজেক্ট

def remove_hostname(domain, hostname):
    domain_copy = deepcopy(domain)
    for domains, hosts in domain_copy.items():
        for host, port in hosts.items():
           if host == hostname:
                del domain[domains][host]
    return domain

উদাহরণস্বরূপ আউটপুট: [অরগিনাল] ডোমেনগুলি = local 'লোকালডোমেন': {'লোকালহোস্ট': {'সব': '4000'}}

[নতুন] ডোমেনগুলি = local 'লোকালডোমেন': {}}}

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


-3

আমি ল্যাসে ভি কার্লসেনের কাছ থেকে অনেক কিছু পছন্দ এবং শিখেছি। আমি এটিকে নিম্নলিখিত উদাহরণে পরিবর্তিত করেছি, যা অগভীর অভিধানের অনুলিপি এবং গভীর অনুলিপিগুলির মধ্যে পার্থক্যটি হাইলাইট করে:

    import copy

    my_dict = {'a': [1, 2, 3], 'b': [4, 5, 6]}
    my_copy = copy.copy(my_dict)
    my_deepcopy = copy.deepcopy(my_dict)

এখন আপনি যদি পরিবর্তন

    my_dict['a'][2] = 7

এবং কর

    print("my_copy a[2]: ",my_copy['a'][2],",whereas my_deepcopy a[2]: ", my_deepcopy['a'][2])

তুমি পাও

    >> my_copy a[2]:  7 ,whereas my_deepcopy a[2]:  3

1
আপনি কেন এই উত্তরটি লাসে ভি কার্লসেনের উত্তরের চেয়ে আলাদা বলে মনে করেন ? এটি কী যুক্ত করে যা অন্য উত্তরটি বলে না?
অলিভিয়ার গ্রাগোয়ার

হাই, অলিভিয়ার! আমি লাসে ভি। কার্লসেনের উত্তরটির যোগ্যতা নেওয়ার চেষ্টা করছি না - তিনি আমার সমস্যাটি মূলত সমাধান করেছেন এবং আমি তার কাছে debtণগ্রস্থ হয়ে পড়েছি। আমার মন্তব্য আলাদা নয়, এটি কেবল পরিপূরক। এটি "ডিপকপি" এর সাথে "অনুলিপি" এর বিপরীতে থাকা সহজ কারণে। এটিই ছিল আমার সমস্যার উত্স, কারণ এগুলি সমতুল্য পদ্ধতিতে ব্যবহার করার সময় আমার ভুল হয়েছিল। চিয়ার্স।
রাফায়েল মন্টেইরো

-9

একটি সহজ (আমার দৃষ্টিতে) সমাধানটি হল একটি নতুন অভিধান তৈরি করা এবং এটি পুরাতনটির বিষয়বস্তু সহ আপডেট করা:

my_dict={'a':1}

my_copy = {}

my_copy.update( my_dict )

my_dict['a']=2

my_dict['a']
Out[34]: 2

my_copy['a']
Out[35]: 1

এই পদ্ধতির সমস্যাটি হ'ল এটি যথেষ্ট গভীর 'নাও হতে পারে। অর্থাত্ পুনরাবৃত্তভাবে গভীর নয়। সাধারণ বস্তুর জন্য যথেষ্ট ভাল তবে নেস্টেড অভিধানের জন্য নয়। এখানে এটি উদাহরণ যেখানে এটি গভীরভাবে নাও হতে পারে:

my_dict1={'b':2}

my_dict2={'c':3}

my_dict3={ 'b': my_dict1, 'c':my_dict2 }

my_copy = {}

my_copy.update( my_dict3 )

my_dict1['b']='z'

my_copy
Out[42]: {'b': {'b': 'z'}, 'c': {'c': 3}}

ডিপকপি () ব্যবহার করে আমি আধা-অগভীর আচরণটি মুছে ফেলতে পারি, তবে আমি মনে করি আপনার আবেদনের জন্য কোন পদ্ধতিটি সঠিক one বেশিরভাগ ক্ষেত্রে আপনি যত্ন নাও করতে পারেন, তবে সম্ভাব্য সমস্যাগুলি সম্পর্কে সচেতন হওয়া উচিত ... চূড়ান্ত উদাহরণ:

import copy

my_copy2 = copy.deepcopy( my_dict3 )

my_dict1['b']='99'

my_copy2
Out[46]: {'b': {'b': 'z'}, 'c': {'c': 3}}

12
এটি ডিকের অগভীর অনুলিপি তৈরি করে, যা প্রশ্নকর্তা যা চেয়েছিলেন তা নয়। এতে থাকা বস্তুগুলি সেগুলি অনুলিপি করা হয় না। এবং অগভীর অনুলিপি করার একটি সহজ উপায় my_dict.copy()!
ব্লকঙ্কহ্ট
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.