python - কিভাবে একটি অভিধান কপি এবং শুধুমাত্র কপি সম্পাদনা




python-3.x dictionary (12)

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

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

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

অতিরিক্ত কীওয়ার্ড আর্গুমেন্ট দিয়ে আপনি dict কন্সট্রাকটরকে কল করে নতুন তৈরি কপি অনুলিপি এবং সম্পাদনা করতে পারেন:

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

অন্যরা যেমন ব্যাখ্যা করেছেন, অন্তর্নির্মিত 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 পরিবর্তন প্যাটার্ন পড়ুন: পাইথন 2.7 - তরল সংশোধন জন্য পরিষ্কার সিনট্যাক্স । মূল পর্যবেক্ষণ হল যে str এবং int পাইথনে মান হিসাবে আচরণ করে (যদিও তারা আসলে হুডের অধীনে অপরিবর্তনীয় বস্তু)। আপনি যে পর্যবেক্ষণ করছেন, এছাড়াও str বা int সম্পর্কে কিছুই স্পষ্টভাবে পালন করা হয় যে পালন করা। একাধিক উপায়ে ValueDict ব্যবহার করা যেতে পারে, এবং আমি অনেক ক্ষেত্রেই ভাবতে পারি যেখানে ValueDict বুঝে।


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

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

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

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

কিন্তু পিছনে compat জন্য, শীর্ষ পদ্ধতি ভাল।


আপনি সরাসরি ব্যবহার করতে পারেন:

dict2 = eval(repr(dict1))

যেখানে বস্তু dict2 dict1 একটি স্বাধীন কপি হয়, তাই আপনি dict1 প্রভাবিত না করে dict2 সংশোধন করতে পারেন।

এটি কোনো বস্তুর জন্য কাজ করে।


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


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

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

এই উদাহরণটি হল ব্লক আইডস সহ সকল ব্যবহারকারী আইডগুলি পেতে। আমরা আইডস পরিবর্তনশীল থেকে পেয়েছি কিন্তু আমরা un_intentionally my_users এর মান আপডেট করেছি। ব্লক_আইডস দিয়ে আইডিকে বর্ধিত করার সময় my_users আপডেট হয়েছে কারণ ids my_users পড়ুন।


পাইথন নিঃসন্দেহে বস্তু কপি করে না। যখন আপনি dict2 = dict1 সেট করেন, তখন আপনি তাদের একই সঠিক নির্দেশ বস্তুটি উল্লেখ করছেন, তাই যখন আপনি এটি পরিবর্তন করেন, তখন এটির সব উল্লেখ তার বর্তমান অবস্থায় বস্তুর উল্লেখ রাখে।

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

dict2 = dict(dict1)

অথবা

dict2 = dict1.copy()

পাইথন প্রতিটি পরিবর্তনশীল ( dict1 বা str অথবা __builtins__ মত dict1 মেশিনের ভিতরে কিছু লুকানো প্ল্যাটনিক "বস্তু" একটি পয়েন্টার।

যদি আপনি dict1 = dict2 সেট dict1 = dict2 , তবে আপনি dict1 হিসাবে শুধুমাত্র একই বস্তুর (অথবা মেমরি অবস্থান, বা আপনি যা উপায়ে চান তা) dict2 । এখন, dict1 দ্বারা উল্লিখিত বস্তু dict1 দ্বারা dict1 একই বস্তু।

আপনি পরীক্ষা করতে পারেন: dict1 is dict2 True হতে হবে। এছাড়াও, id(dict1) হিসাবে একই হওয়া উচিত।

আপনি dict1 = copy(dict2) , অথবা dict1 = deepcopy(dict2) dict1 = copy(dict2) চান।

copy এবং deepcopy copy মধ্যে পার্থক্য? deepcopy নিশ্চিত করবে যে dict2 এর উপাদানগুলি (আপনি এটি একটি তালিকাতে নির্দেশ করেছেন?) এছাড়াও কপি।

আমি deepcopy ব্যবহার করি না - সাধারণত এটির জন্য প্রয়োজনীয় কোড লিখতে খারাপ অনুশীলন (আমার মতে)।


যখন আপনি dict2 = dict1 বরাদ্দ dict2 = dict1 , আপনি dict2 = dict1 একটি অনুলিপি তৈরি করছেন না, এটি dict2 জন্য dict1 জন্য অন্য নাম হচ্ছে।

deepcopy মত পরিবর্তনযোগ্য প্রকারগুলি অনুলিপি করতে, copy মডিউলের copy / deepcopy copy ব্যবহার করুন।

import copy

dict2 = copy.deepcopy(dict1)

dict1 একটি প্রতীক যা একটি অন্তর্নিহিত অভিধান বস্তু উল্লেখ করে। dict1 dict2 শুধুমাত্র একই রেফারেন্স বরাদ্দ। dict2 চিহ্নের মাধ্যমে একটি কী এর মান পরিবর্তনকারী অন্তর্নিহিত বস্তু পরিবর্তন করে, যা dict1 প্রভাবিত dict1 । এটা সন্দ্বিহান.

রেফারেন্সের চেয়ে অপরিবর্তনীয় মান সম্পর্কে যুক্তি করা অনেক সহজ, তাই যখনই সম্ভব কপি করুন:

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

এটি সিনট্যাক্টিকভাবে একই রকম:

one_year_later = dict(person, age=26)

পাইথন 2.7 এবং 3 উভয়েই একটি কপির একটি কপি তৈরি করার সেরা এবং সহজতম উপায় ...

সাধারণ (একক স্তরের) অভিধানের একটি অনুলিপি তৈরি করতে:

1. বিদ্যমান শব্দ নির্দেশ করে একটি রেফারেন্স উৎপন্ন করার পরিবর্তে dict () পদ্ধতি ব্যবহার করে।

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)

>>> 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)






reference