ডিক্টকপি () বোঝা - অগভীর নাকি গভীর?


429

এর জন্য ডকুমেন্টেশন পড়ার সময় dict.copy(), এটি বলে যে এটি অভিধানের অগভীর অনুলিপি তৈরি করে। আমি অনুসরণ করছি বইটির জন্য একই (বেজলির পাইথন রেফারেন্স), যা বলে:

M.copy () পদ্ধতিটি ম্যাপিং অবজেক্টে থাকা আইটেমগুলির অগভীর অনুলিপি তৈরি করে একটি নতুন ম্যাপিং অবজেক্টে রাখে।

এই বিবেচনা:

>>> original = dict(a=1, b=2)
>>> new = original.copy()
>>> new.update({'c': 3})
>>> original
{'a': 1, 'b': 2}
>>> new
{'a': 1, 'c': 3, 'b': 2}

সুতরাং আমি ধরে originalনিয়েছি যে এটি অগভীর অনুলিপিটি করার পরেও (এবং 'সি': 3 যোগ করে) এর মান আপডেট করবে । আপনি যদি এটি তালিকার জন্য করেন তবে পছন্দ করুন:

>>> original = [1, 2, 3]
>>> new = original
>>> new.append(4)
>>> new, original
([1, 2, 3, 4], [1, 2, 3, 4])

এটি প্রত্যাশার মতো কাজ করে।

যেহেতু উভয়ই অগভীর অনুলিপি, কেন এটি dict.copy()আমার প্রত্যাশা মতো কাজ করে না? অথবা অগভীর বনাম গভীর অনুলিপি সম্পর্কে আমার বোঝা ত্রুটিযুক্ত?


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

উত্তর:


990

"অগভীর অনুলিপি" দ্বারা এর অর্থ অভিধানের সামগ্রীটি মান দ্বারা অনুলিপি করা হয়নি, তবে কেবল একটি নতুন রেফারেন্স তৈরি করা উচিত।

>>> a = {1: [1,2,3]}
>>> b = a.copy()
>>> a, b
({1: [1, 2, 3]}, {1: [1, 2, 3]})
>>> a[1].append(4)
>>> a, b
({1: [1, 2, 3, 4]}, {1: [1, 2, 3, 4]})

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

>>> import copy
>>> c = copy.deepcopy(a)
>>> a, c
({1: [1, 2, 3, 4]}, {1: [1, 2, 3, 4]})
>>> a[1].append(5)
>>> a, c
({1: [1, 2, 3, 4, 5]}, {1: [1, 2, 3, 4]})

তাই:

  1. b = a: রেফারেন্স অ্যাসাইনমেন্ট, মেক aএবং bএকই বস্তুর দিকে নির্দেশ করে points

    'A = b': 'a' এবং 'b' উভয়ের চিত্র '{1: L}', 'L' নির্দেশ করে '[1, 2, 3]'।

  2. b = a.copy(): অগভীর অনুলিপি করা, aএবং bদুটি পৃথক পৃথক বস্তুতে পরিণত হবে, তবে তাদের বিষয়বস্তু এখনও একই রেফারেন্স ভাগ করে

    'B = a.copy ()' এর চিত্র: 'a' '{1: L}', 'b' কে '{1: M}', 'L' এবং 'M' উভয় বিন্দুতে নির্দেশ করে [ 1, 2, 3] '।

  3. b = copy.deepcopy(a): গভীর অনুলিপি করা, aএবং bএর কাঠামো এবং সামগ্রী সম্পূর্ণ বিচ্ছিন্ন হয়ে যায় become

    'খ = অনুলিপি.দীপকপি (ক)' এর চিত্র: 'এ' '{1: এল}', 'এল' পয়েন্টগুলিকে '[1, 2, 3]';  'বি' '{1: এম}', 'এম' '[1, 2, 3]' এর ভিন্ন উদাহরণকে নির্দেশ করে।


উত্তম উত্তর, তবে আপনি প্রথম বাক্যে ব্যাকরণগত ত্রুটি সংশোধন করার বিষয়টি বিবেচনা করতে পারেন। এবং Lআবার ব্যবহার না করার কোনও কারণ নেই b। এটি করা উদাহরণটিকে সহজ করে তুলবে।
টম রাসেল

@ কেনিটিএম: আসলে প্রথম দুটি উদাহরণের মধ্যে পার্থক্য কী? আপনি সেখানে একই ফলাফল পেয়ে যাচ্ছেন, তবে অভ্যন্তরীণ বাস্তবায়ন থেকে কিছুটা আলাদা, তবে কীসের জন্য এটি গুরুত্বপূর্ণ?
জাভাসা

@ টমরসেল: বা যে কেউ, যেহেতু এই প্রশ্নটি বেশ পুরানো, আমার
স্পষ্টির প্রশ্নটি

@ জাভাসা যদি তা করে, তবে তা গুরুত্বপূর্ণ b[1][0] = 5। যদি bঅগভীর অনুলিপি হয় তবে আপনি সবেমাত্র পরিবর্তন করেছেন a[1][0]
টম রাসেল

2
দুর্দান্ত ব্যাখ্যা, ... সত্যিই আমার দিনটি বাঁচিয়েছে! ধন্যবাদ ... এটি কি পাইপ, পাইথন, এবং পাইথনের অন্যান্য ডেটাটাইপগুলি টিপিকে টিপি প্রয়োগ করা যেতে পারে?
ভুরু

38

এটি গভীর অনুলিপি বা অগভীর অনুলিপিয়ের বিষয় নয়, আপনি যা করছেন তা কোনও কিছুই অনুলিপি নয়।

এখানে:

>>> new = original 

আপনি তালিকার / ডিক্সের দ্বারা মূল অনুসারে একটি নতুন রেফারেন্স তৈরি করছেন।

এখানে থাকাকালীন:

>>> new = original.copy()
>>> # or
>>> new = list(original) # dict(original)

আপনি একটি নতুন তালিকা / ডিক তৈরি করছেন যা মূল ধারকটিতে থাকা অবজেক্টের রেফারেন্সের একটি অনুলিপি দ্বারা পূর্ণ।


31

এই উদাহরণটি ধরুন:

original = dict(a=1, b=2, c=dict(d=4, e=5))
new = original.copy()

এখন আসুন 'অগভীর' (প্রথম) স্তরের মান পরিবর্তন করুন:

new['a'] = 10
# new = {'a': 10, 'b': 2, 'c': {'d': 4, 'e': 5}}
# original = {'a': 1, 'b': 2, 'c': {'d': 4, 'e': 5}}
# no change in original, since ['a'] is an immutable integer

এবার আসুন এক মান আরও গভীরতর করে:

new['c']['d'] = 40
# new = {'a': 10, 'b': 2, 'c': {'d': 40, 'e': 5}}
# original = {'a': 1, 'b': 2, 'c': {'d': 40, 'e': 5}}
# new['c'] points to the same original['d'] mutable dictionary, so it will be changed

8
no change in original, since ['a'] is an immutable integerএই. এটি আসলে জিজ্ঞাসিত প্রশ্নের উত্তর দেয়।
সিভিফ্যান

8

কেনেটিমের উত্তরে যুক্ত করা হচ্ছে। যখন আপনি একটি অগভীর কপি না parent.copy () একটি নতুন অভিধান একই কী দিয়ে তৈরি করা হয়, কিন্তু মান অনুলিপি করা হয়নি তারা referenced.If আপনি একটি নতুন মান যোগ parent_copy এটা করবে না প্রভাব পিতা বা মাতা কারণ parent_copy একটি নতুন অভিধান হল রেফারেন্স না।

parent = {1: [1,2,3]}
parent_copy = parent.copy()
parent_reference = parent

print id(parent),id(parent_copy),id(parent_reference)
#140690938288400 140690938290536 140690938288400

print id(parent[1]),id(parent_copy[1]),id(parent_reference[1])
#140690938137128 140690938137128 140690938137128

parent_copy[1].append(4)
parent_copy[2] = ['new']

print parent, parent_copy, parent_reference
#{1: [1, 2, 3, 4]} {1: [1, 2, 3, 4], 2: ['new']} {1: [1, 2, 3, 4]}

প্যারেন্ট [1] , প্যারেন্ট_কপি [1] এর হ্যাশ (আইডি) মানটি একই রকম যা 140690938288400 আইডিতে সঞ্চিত [1] এবং পিতামাতার_কপি [1] এর [1,2,3] বোঝায় ।

তবে পিতা - মাতার এবং পিতা - মাতার_কপির হ্যাশ পৃথক রয়েছে যা বোঝায় যে এগুলি বিভিন্ন অভিধান এবং প্যারেন্ট_কপি একটি নতুন অভিধান যা পিতামাতার মানগুলির সাথে মান উল্লেখ করে


5

"নতুন" এবং "অরিজিনাল" আলাদা আলাদা ডিক্টস, এজন্য আপনি কেবল তার মধ্যে একটি আপডেট করতে পারেন .. আইটেমগুলি অগভীর-অনুলিপি করা হয়, ডিক নিজেই নয়।


2

বিষয়বস্তু অগভীর অনুলিপি করা হয়।

সুতরাং যদি আসলটিতে dictএকটি listবা অন্য থাকে dictionary, তবে সেগুলিকে একটিতে আসল বা তার অগভীর অনুলিপিতে সংশোধন করে অন্যকে ( listবা বা dict) সংশোধন করবে ।


1

আপনার দ্বিতীয় অংশে, আপনার ব্যবহার করা উচিত new = original.copy()

.copyএবং =বিভিন্ন জিনিস।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.