Python-এর dict ক্লাসে ডিকশনারি নিয়ে কাজ করার জন্য অনেকগুলো কাজের মেথড আছে।
এর কয়েকটি dicts-এর কনসেপ্টে আগেই আলোচনা করা হয়েছে।
এখানে আমরা আরও কয়েকটি মেথড নিয়ে আলোচনা করব, সাথে থাকবে ডিকশনারির মধ্য দিয়ে ইটারেট করা ও সেগুলো ম্যানিপুলেট করার কিছু কৌশলও।
setdefault() ব্যবহার করুনডিকশনারি কনসেপ্টে আগে বলা হয়েছিল যে ডিকশনারিতে একটা key খুঁজে না পেলে .get(key, <default value>) একটি বিদ্যমান value বা default value রিটার্ন করে, আর এভাবেই একটা KeyError এড়ানো যায়।
আপনি যখন বাড়তি এরর হ্যান্ডলিং চান না, কিন্তু যে key খুঁজছেন সেটা থাকবে বলে ভরসা করতে পারেন না, এমন পরিস্থিতিতে এটা ভালোই কাজ করে।
একইভাবে "নিরাপদ" (KeyError ছাড়া) ইনসার্ট করার জন্য আছে .setdefault(key, <default value>) মেথডটি।
ডিকশনারিতে key পাওয়া গেলে setdefault(key, <default value>) ওই value রিটার্ন করবে।
key না পাওয়া গেলে এটি (key, default value) জোড়াটি ইনসার্ট করবে এবং ব্যবহারের জন্য default value রিটার্ন করবে।
>>> palette_I = {'Grassy Green': '#9bc400', 'Purple Mountains Majesty': '#8076a3', 'Misty Mountain Pink': '#f9c5bd'}
# Looking for the value associated with key "Rock Brown".
# The key does not exist, so it is added with the default value, and the value is returned.
>>> palette_I.setdefault('Rock Brown', '#694605')
'#694605'
# The (key, default value) pair has now been added to the dictionary.
>>> palette_I
{'Grassy Green': '#9bc400', 'Purple Mountains Majesty': '#8076a3', 'Misty Mountain Pink': '#f9c5bd', 'Rock Brown': '#694605'}
fromkeys() ব্যবহার করুনবিভিন্ন keys ও ডিফল্ট মান দিয়ে দ্রুত একটি ডিকশনারি ভরাতে, ক্লাস মেথড fromkeys(iterable, <default value>) keys-এর একটি ইটারেবলের উপর ইটারেট করে একটি নতুন dict তৈরি করবে।
সব values প্রদত্ত default value-তে সেট হয়ে যাবে:
>>> new_dict = dict.fromkeys(['Grassy Green', 'Purple Mountains Majesty', 'Misty Mountain Pink'], 'fill in hex color here')
{'Grassy Green': 'fill in hex color here',
'Purple Mountains Majesty': 'fill in hex color here',
'Misty Mountain Pink': 'fill in hex color here'}
.keys(), .values() ও .items() মেথডগুলো একটি ডিকশনারির ইটারেবল ভিউ রিটার্ন করে।
এই ভিউগুলো ব্যবহার করে এন্ট্রিগুলোর উপর সহজে লুপ করা যায়, সেগুলো না বদলেই।
ভিউ আবার _ডাইনামিক_ও। আন্ডারলাইং ডিকশনারি ডেটা বদলালে সংশ্লিষ্ট view object সেই পরিবর্তনটি প্রতিফলিত করে:
>>> palette_I = {'Grassy Green': '#9bc400',
'Purple Mountains Majesty': '#8076a3',
'Misty Mountain Pink': '#f9c5bd'}
# Using .keys() returns a list of keys.
>>> palette_I.keys()
dict_keys(['Grassy Green', 'Purple Mountains Majesty', 'Misty Mountain Pink'])
# Using .values() returns a list of values.
>>> palette_I.values()
dict_values(['#9bc400', '#8076a3', '#f9c5bd'])
# Using .items() returns a list of (key, value) tuples.
>>> palette_I.items()
dict_items([('Grassy Green', '#9bc400'), ('Purple Mountains Majesty', '#8076a3'), ('Misty Mountain Pink', '#f9c5bd')])
# Views are dynamic. Changing values in the dict changes all of the associated views.
>>> palette_I['Purple Mountains Majesty'] = (128, 118, 163)
>>> palette_I['Deep Red'] = '#932432'
>>> palette_I.values()
dict_values(['#9bc400', (128, 118, 163), '#f9c5bd', '#932432'])
>>> palette_I.keys()
dict_keys(['Grassy Green', 'Purple Mountains Majesty', 'Misty Mountain Pink', 'Deep Red'])
>>> palette_I.items()
dict_items([('Grassy Green', '#9bc400'), ('Purple Mountains Majesty', (128, 118, 163)), ('Misty Mountain Pink', '#f9c5bd'), ('Deep Red', '#932432')])
.keys(), .values() ও .items() নিয়ে আরও কিছুPython 3.7 এবং তার পরের ভার্সনে dicts এন্ট্রিগুলো যে ক্রমে ইনসার্ট করা হয় সেই ক্রম ধরে রাখে, ফলে .keys(), .values() বা .items() ব্যবহার করার সময় First-in, First-out (FIFO) ক্রমে ইটারেশন করা যায়।
Python 3.8 এবং তার পরের ভার্সনে ভিউগুলো _রিভার্সিবল_ও।
এর ফলে reversed(<dict>.keys()), reversed(<dict>.values()) বা reversed(<dict>.items()) ব্যবহার করে কী (key), মান বা (key, value) জোড়াগুলোর উপর Last-in, First-out (LIFO) ক্রমে ইটারেট করা যায়:
>>> palette_II = {'Factory Stone Purple': '#7c677f', 'Green Treeline': '#478559', 'Purple baseline': '#161748'}
# Iterating in insertion order (First in, first out)
>>> for item in palette_II.items():
... print(item)
...
('Factory Stone Purple', '#7c677f')
('Green Treeline', '#478559')
('Purple baseline', '#161748')
# Iterating in the reverse direction. (Last in, first out)
>>> for item in reversed(palette_II.items()):
... print (item)
...
('Purple baseline', '#161748')
('Green Treeline', '#478559')
('Factory Stone Purple', '#7c677f')
ডিকশনারিতে বিল্ট-ইন সর্টিং মেথড নেই।
তবে বিল্ট-ইন ফাংশন sorted()-এর সাথে dict.items() ব্যবহার করে একটি dict ভিউ সর্ট করা সম্ভব।
এরপর সর্ট করা ভিউটি দিয়ে একটি নতুন ডিকশনারি তৈরি করা যায়।
ইটারেশনের মতোই, ডিফল্ট সর্ট হয় ডিকশনারির keys-এর উপর।
# Default ordering for a dictionary is insertion order (First in, first out).
>>> color_palette = {'Grassy Green': '#9bc400',
'Purple Mountains Majesty': '#8076a3',
'Misty Mountain Pink': '#f9c5bd',
'Factory Stone Purple': '#7c677f',
'Green Treeline': '#478559',
'Purple baseline': '#161748'}
# The default sort order for a dictionary uses the keys.
>>> sorted_palette = dict(sorted(color_palette.items()))
>>> sorted_palette
{'Factory Stone Purple': '#7c677f',
'Grassy Green': '#9bc400',
'Green Treeline': '#478559',
'Misty Mountain Pink': '#f9c5bd',
'Purple Mountains Majesty': '#8076a3',
'Purple baseline': '#161748'}
.update() দিয়ে ডিকশনারি একত্র করা<dict_one>.update(<dict_two>) দিয়ে দুটি ডিকশনারি একত্র করা যায়।
এই মেথডটি <dict_two>-এর (key,value) জোড়াগুলো নিয়ে সেগুলো <dict_one>-এ লিখে দেবে:
>>> palette_I = {'Grassy Green': '#9bc400',
'Purple Mountains Majesty': '#8076a3',
'Misty Mountain Pink': '#f9c5bd'}
>>> palette_II = {'Factory Stone Purple': '#7c677f',
'Green Treeline': '#478559',
'Purple Baseline': '#161748'}
>>> palette_I.update(palette_II)
# Note that new items from palette_II are added.
>>> palette_I
{'Grassy Green': '#9bc400', 'Purple Mountains Majesty': '#8076a3', 'Misty Mountain Pink': '#f9c5bd', 'Factory Stone Purple': '#7c677f', 'Green Treeline': '#478559', 'Purple Baseline': '#161748'}
দুটি ডিকশনারিতে কী (key) ওভারল্যাপ করলে, dict_one-এর value dict_two-এর সংশ্লিষ্ট value দিয়ে ওভাররাইট হয়ে যাবে:
>>> palette_I = {'Grassy Green': '#9bc400', 'Purple Mountains Majesty': '#8076a3', 'Misty Mountain Pink': '#f9c5bd',
'Factory Stone Purple': '#7c677f', 'Green Treeline': '#478559', 'Purple baseline': '#161748'}
>>> palette_III = {'Grassy Green': (155, 196, 0), 'Purple Mountains Majesty': (128, 118, 163),
'Misty Mountain Pink': (249, 197, 189)}
>>> palette_I.update(palette_III)
# Overlapping values in palette_I are replaced with values from palette_III
>>> palette_I
{'Grassy Green': (155, 196, 0),
'Purple Mountains Majesty': (128, 118, 163),
'Misty Mountain Pink': (249, 197, 189),
'Factory Stone Purple': '#7c677f',
'Green Treeline': '#478559', 'Purple baseline': '#161748'}
| ও |=) অপারেটর দিয়ে ডিকশনারি মার্জ বা আপডেট করাPython 3.9 dicts মার্জ করার একটি ভিন্ন উপায় নিয়ে আসে: union অপারেটরগুলো।
dict_one | dict_two একটি নতুন ডিকশনারি তৈরি করবে, যা dict_one ও dict_two-এর (key, value) জোড়া দিয়ে গঠিত।
দুটি ডিকশনারিতে কী (key) একই থাকলে, dict_two-এর মানগুলো প্রাধান্য পায়।
>>> palette_I = {'Grassy Green': '#9bc400', 'Purple Mountains Majesty': '#8076a3', 'Misty Mountain Pink': '#f9c5bd'}
>>> palette_II = {'Factory Stone Purple': '#7c677f', 'Green Treeline': '#478559', 'Purple baseline': '#161748'}
>>> new_dict = palette_I | palette_II
>>> new_dict
...
{'Grassy Green': '#9bc400',
'Purple Mountains Majesty': '#8076a3',
'Misty Mountain Pink': '#f9c5bd',
'Factory Stone Purple': '#7c677f',
'Green Treeline': '#478559',
'Purple baseline': '#161748'}
dict_one |= other অনেকটা <dict_one>.update(<other>)-এর মতো আচরণ করে, তবে এক্ষেত্রে other একটি dict বা (key, value) জোড়ার একটি ইটারেবল, এই দুটোর যেকোনোটি হতে পারে:
>>> palette_III = {'Grassy Green': (155, 196, 0),
'Purple Mountains Majesty': (128, 118, 163),
'Misty Mountain Pink': (249, 197, 189)}
>>> new_dict |= palette_III
>>> new_dict
...
{'Grassy Green': (155, 196, 0),
'Purple Mountains Majesty': (128, 118, 163),
'Misty Mountain Pink': (249, 197, 189),
'Factory Stone Purple': '#7c677f',
'Green Treeline': '#478559',
'Purple baseline': '#161748'}
ডিকশনারি ও সেগুলো নিয়ে কাজ করার মেথড সম্পর্কে বিস্তারিত ব্যাখ্যার জন্য অফিসিয়াল টিউটোরিয়াল ও অফিসিয়াল লাইব্রেরি রেফারেন্স চমৎকার শুরুর জায়গা।
Real Python ও Finxter-এও Python ডিকশনারি নিয়ে খুবই পূর্ণাঙ্গ আর্টিকেল আছে।
Mecha Munch™, একটি গ্রোসারি শপিং অটোমেশন কোম্পানি, তাদের অর্ডারিং অ্যাপে কাজ করার জন্য আপনাকে সদ্য নিয়োগ করেছে। আপনার টিমকে একটি MVP (ন্যূনতম কার্যকর পণ্য) তৈরির দায়িত্ব দেওয়া হয়েছে, যা শপিং কার্টের সব মৌলিক কাজ পরিচালনা করবে এবং ব্যবহারকারীদের তাদের গ্রোসারি অর্ডার যোগ করতে, মুছে ফেলতে ও সাজাতে দেবে। ভাগ্যক্রমে, সব টাকা ও চেক-আউট সংক্রান্ত কাজ অন্য একটি টিম সামলাচ্ছে!
MVP-তে ব্যবহারকারীর শপিং কার্টে আইটেম যোগ করার সুবিধা থাকতে হবে। এটি একসাথে একটি আইটেমও হতে পারে, আবার একাধিক আইটেমও হতে পারে। যেহেতু এটি একটি MVP, তাই আইটেমের পরিমাণ বোঝানো হয় পুনরাবৃত্তির মাধ্যমে। কোনো ব্যবহারকারী যদি ২টি Orange যোগ করতে চান, তবে ইনপুট ইটারেবলে 'Oranges' দুইবার থাকবে। ব্যবহারকারীর কার্টে আইটেমটি আগে থেকেই থাকলে কার্টের পরিমাণ ১ বাড়ানো উচিত। আর আইটেমটি কার্টে নতুন হলে, তা ১ পরিমাণ নিয়ে যোগ করতে হবে।
add_item(<current_cart>, <items_to_add>) ফাংশনটি তৈরি করুন, যা আর্গুমেন্ট হিসেবে একটি কার্ট ডিকশনারি এবং যোগ করার জন্য যেকোনো লিস্ট-সদৃশ ইটারেবল নেয়। এটি ব্যবহারকারীর জন্য নতুন/হালনাগাদ করা একটি শপিং কার্ট ডিকশনারি রিটার্ন করবে।
>>> add_item({'Banana': 3, 'Apple': 2, 'Orange': 1},
('Apple', 'Apple', 'Orange', 'Apple', 'Banana'))
{'Banana': 4, 'Apple': 5, 'Orange': 2}
>>> add_item({'Banana': 3, 'Apple': 2, 'Orange': 1},
['Banana', 'Orange', 'Blueberries', 'Banana'])
{'Banana': 5, 'Apple': 2, 'Orange': 2, 'Blueberries': 1}
উফ! মনে হচ্ছে প্রোডাক্ট টিম ফিচার ক্রিপ-এ জড়িয়ে পড়ছে। তারা MVP-তে বাড়তি ফিচার যোগ করতে চায়। এখন অ্যাপটিকে ব্যবহারকারীর নোট অ্যাপ থেকে আইটেম পড়ে একটি শপিং কার্ট তৈরি করতে হবে। ব্যবহারকারীদের জন্য সুবিধাজনক, কিন্তু টিমের জন্য একটু বেশি পরিশ্রম।
read_notes(<notes>) ফাংশনটি তৈরি করুন, যা আর্গুমেন্ট হিসেবে যেকোনো লিস্ট-সদৃশ ইটারেবল নিতে পারবে। ফাংশনটি আইটেমগুলো পার্স করে একটি ব্যবহারকারীর শপিং কার্ট/ডিকশনারি তৈরি করবে। প্রতিটি আইটেম ১ পরিমাণ নিয়ে যোগ করতে হবে। এরপর নতুন ব্যবহারকারী কার্টটি রিটার্ন করতে হবে।
>>> read_notes(('Banana','Apple', 'Orange'))
{'Banana': 1, 'Apple': 1, 'Orange': 1}
>>> read_notes(['Blueberries', 'Pear', 'Orange', 'Banana', 'Apple'])
{'Blueberries' : 1, 'Pear' : 1, 'Orange' : 1, 'Banana' : 1, 'Apple' : 1}
অ্যাপটিতে একটি "আইডিয়া" সেকশন আছে, যা নানা খাবারের তৈরি রেসিপিতে ভরপুর। ব্যবহারকারী এই রেসিপিগুলোর যেকোনো একটি বেছে নিতে পারেন, আর তার সব উপকরণ স্বয়ংক্রিয়ভাবে তার শপিং কার্টে যোগ হয়ে যায়। প্রজেক্ট ম্যানেজার আপনাকে এই "আইডিয়া" রেসিপিগুলো সম্পাদনা করার একটি উপায় তৈরি করতে বলেছেন, কারণ কনটেন্ট টিম সবসময় উপকরণ ও পরিমাণ বদলে চলেছে।
update_recipes(<ideas>, <recipe_updates>) ফাংশনটি তৈরি করুন, যা আর্গুমেন্ট হিসেবে একটি "আইডিয়া" ডিকশনারি এবং রেসিপি হালনাগাদের একটি ইটারেবল নেয়। ফাংশনটি নতুন/হালনাগাদ করা "আইডিয়া" ডিকশনারি রিটার্ন করবে।
>>>update_recipes(
{'Banana Bread' : {'Banana': 1, 'Apple': 1, 'Walnuts': 1, 'Flour': 1, 'Eggs': 2, 'Butter': 1},
'Raspberry Pie' : {'Raspberry': 1, 'Orange': 1, 'Pie Crust': 1, 'Cream Custard': 1}},
(('Banana Bread', {'Banana': 4, 'Walnuts': 2, 'Flour': 1, 'Butter': 1, 'Milk': 2, 'Eggs': 3}),)
)
...
{'Banana Bread': {'Banana': 4, 'Walnuts': 2, 'Flour': 1, 'Butter': 1, 'Milk': 2, 'Eggs': 3},
'Raspberry Pie': {'Raspberry': 1, 'Orange': 1, 'Pie Crust': 1, 'Cream Custard': 1}}
>>> update_recipes(
{'Banana Bread' : {'Banana': 1, 'Apple': 1, 'Walnuts': 1, 'Flour': 1, 'Eggs': 2, 'Butter': 1},
'Raspberry Pie' : {'Raspberry': 1, 'Orange': 1, 'Pie Crust': 1, 'Cream Custard': 1},
'Pasta Primavera': {'Eggs': 1, 'Carrots': 1, 'Spinach': 2, 'Tomatoes': 3, 'Parmesan': 2, 'Milk': 1, 'Onion': 1}},
[('Raspberry Pie', {'Raspberry': 3, 'Orange': 1, 'Pie Crust': 1, 'Cream Custard': 1, 'Whipped Cream': 2}),
('Pasta Primavera', {'Eggs': 1, 'Mixed Veggies': 2, 'Parmesan': 2, 'Milk': 1, 'Spinach': 1, 'Bread Crumbs': 1}),
('Blueberry Crumble', {'Blueberries': 2, 'Whipped Creme': 2, 'Granola Topping': 2, 'Yogurt': 3})]
)
...
{'Banana Bread': {'Banana': 1, 'Apple': 1, 'Walnuts': 1, 'Flour': 1, 'Eggs': 2, 'Butter': 1},
'Raspberry Pie': {'Raspberry': 3, 'Orange': 1, 'Pie Crust': 1, 'Cream Custard': 1, 'Whipped Cream': 2},
'Pasta Primavera': {'Eggs': 1, 'Mixed Veggies': 2, 'Parmesan': 2, 'Milk': 1, 'Spinach': 1, 'Bread Crumbs': 1},
'Blueberry Crumble': {'Blueberries': 2, 'Whipped Creme': 2, 'Granola Topping': 2, 'Yogurt': 3}}
ব্যবহারকারী কার্ট শুরু করার পর অ্যাপটি তাদের আইটেম বর্ণানুক্রমে সাজানোর সুযোগ দেয়। এতে জিনিস খুঁজে পাওয়া সহজ হয়, আর ডেটা এন্ট্রির ভুল ধরতেও সুবিধা হয়, যেমন ডেটাবেসে 'potatoes' ও 'Potato' একসাথে থাকা।
sort_entries(<cart>) ফাংশনটি তৈরি করুন, যা আর্গুমেন্ট হিসেবে একটি শপিং কার্ট/ডিকশনারি নেয় এবং বর্ণানুক্রমে সাজানো একটি নতুন কার্ট রিটার্ন করে।
>>> sort_entries({'Banana': 3, 'Apple': 2, 'Orange': 1})
{'Apple': 2, 'Banana':3, 'Orange': 1}
অ্যাপটিকে একটি নির্দিষ্ট ব্যবহারকারীর কার্ট পূরণের জন্য দোকানে পাঠাতে হবে। তবে দোকানের কর্মীদের জানা দরকার, কোন আইটেম দোকানের কোন আইলে পাওয়া যায় এবং আইটেমটির ফ্রিজে রাখার প্রয়োজন আছে কি না। তাই (বেশ খামখেয়ালিভাবেই) "পূরণ কার্ট"-টি এমনভাবে সাজাতে হবে যাতে আইটেমগুলো বিপরীত বর্ণানুক্রমে থাকে এবং প্রতিটির পরিমাণের সাথে অবস্থান ও ফ্রিজে রাখার তথ্য যুক্ত থাকে।
send_to_store(<cart>, <aisle_mapping>) ফাংশনটি তৈরি করুন, যা আর্গুমেন্ট হিসেবে একটি ব্যবহারকারীর শপিং কার্ট এবং একটি ডিকশনারি নেয়, যেখানে প্রতিটি আইটেমের জন্য দোকানের আইল নম্বর এবং ফ্রিজে রাখার প্রয়োজন আছে কি না তা বোঝাতে True/False থাকে।
ফাংশনটি একটি সম্মিলিত "পূরণ কার্ট" return করবে, যেখানে গ্রাহকের অর্ডার করা প্রতিটি আইটেমের জন্য (পরিমাণ, আইল ও ফ্রিজে রাখার তথ্য) থাকবে।
আইটেমগুলো বিপরীত বর্ণানুক্রমে থাকা উচিত।
>>> send_to_store({'Banana': 3, 'Apple': 2, 'Orange': 1, 'Milk': 2},
{'Banana': ['Aisle 5', False], 'Apple': ['Aisle 4', False], 'Orange': ['Aisle 4', False], 'Milk': ['Aisle 2', True]})
{'Orange': [1, 'Aisle 4', False], 'Milk': [2, 'Aisle 2', True], 'Banana': [3, 'Aisle 5', False], 'Apple': [2, 'Aisle 4', False]}
অ্যাপটি কেবল অবিরাম গ্রাহকের অর্ডার নিয়েই চলতে পারে না। একসময় দোকানের নানা পণ্য ফুরিয়ে যাবে। তাই আপনার MVP অ্যাপটিকে প্রতিবার ব্যবহারকারী তার অর্ডার দোকানে পাঠালে দোকানের স্টক হালনাগাদ করতে হবে। নাহলে গ্রাহকরা এমন পণ্য অর্ডার করবেন যা আসলে মজুত নেই।
update_store_inventory(<fulfillment_cart>, <store_inventory>) ফাংশনটি তৈরি করুন, যা আর্গুমেন্ট হিসেবে একটি "পূরণ কার্ট" এবং একটি দোকানের স্টক নেয়।
ফাংশনটি "পূরণ কার্ট"-এ "অর্ডার করা" সংখ্যা অনুযায়ী দোকানের স্টকের পরিমাণ কমাবে, তারপর হালনাগাদ করা দোকানের স্টক রিটার্ন করবে।
কোনো স্টক আইটেমের সংখ্যা 0-এ নেমে এলে সেই সংখ্যার জায়গায় 'Out of Stock' বার্তাটি বসাতে হবে।
>>> update_store_inventory({'Orange': [1, 'Aisle 4', False], 'Milk': [2, 'Aisle 2', True], 'Banana': [3, 'Aisle 5', False], 'Apple': [2, 'Aisle 4', False]},
{'Banana': [15, 'Aisle 5', False], 'Apple': [12, 'Aisle 4', False], 'Orange': [1, 'Aisle 4', False], 'Milk': [4, 'Aisle 2', True]})
{'Banana': [12, 'Aisle 5', False], 'Apple': [10, 'Aisle 4', False], 'Orange': ['Out of Stock', 'Aisle 4', False], 'Milk': [2, 'Aisle 2', True]}
Exercism-এ সাইন আপ করুন, Python ট্র্যাকের 17টি কনসেপ্ট146টি অনুশীলনী আর সত্যিকারের মানুষের মেন্টরিং দিয়ে শিখুন ও দক্ষ হয়ে উঠুন, সম্পূর্ণ বিনামূল্যে।