মূল পার্থক্য
ইমিউটেবল অবজেক্ট (int, float, str, tuple) এর জন্য a += b এবং a = a + b একই ফলাফল দেয় (নতুন অবজেক্ট তৈরি হয়)। কিন্তু মিউটেবল অবজেক্ট (list, dict, set) এর জন্য a += b ইন-প্লেস মডিফিকেশন করে (একই অবজেক্ট আপডেট হয়), যেখানে a = a + b নতুন অবজেক্ট তৈরি করে।
কেস ১: a = a + b (নতুন অবজেক্ট)
x = 'Hello '
z_list = [1, 2, 3]
z_list = z_list + x # TypeError: can only concatenate list (not "str") to list
এরর:
TypeError: can only concatenate list (not "str") to list
+ অপারেটর লিস্টের জন্য শুধু লিস্ট এক্সেপ্ট করে।
কেস ২: a += b (ইন-প্লেস এক্সটেন্ড)
z_list = [1, 2, 3]
x = 'Hello'
z_list += x # স্ট্রিংকে ইটারেবল ধরে ক্যারেক্টার বাই ক্যারেক্টার এক্সটেন্ড করে
print(z_list)
# আউটপুট: [1, 2, 3, 'H', 'e', 'l', 'l', 'o']
কেন এত পার্থক্য?
a = a + b→a.__add__(b)কল করে, রিটার্ন ভ্যালু নতুন অবজেক্টে অ্যাসাইন করে।a += b→a.__iadd__(b)কল করে (যদি থাকে), যা ইন-প্লেস মডিফাই করে এবংselfরিটার্ন করে। লিস্টের__iadd__হলোextend()সমতুল্য, যেকোনো ইটারেবল এক্সেপ্ট করে।
ডিকশনারি উদাহরণ
d1 = {'a': 1}
d2 = {'b': 2}
d1 += d2 # TypeError: 'dict' object does not support +=
# ডিক্টে __iadd__ নেই
d1 = d1 | d2 # পাইথন ৩.৯+ মার্জ (নতুন ডিক্ট)
d1 |= d2 # ইন-প্লেস মার্জ (পাইথন ৩.৯+)
সেট উদাহরণ
s1 = {1, 2}
s2 = {3, 4}
s1 += s2 # TypeError: 'set' object does not support +=
s1 |= s2 # ইন-প্লেস ইউনিয়ন (OK)
s1.update(s2) # একই কাজ
সারসংক্ষেপ
| অপারেশন | ইমিউটেবল (int, str) | লিস্ট | ডিক্ট/সেট |
|---|---|---|---|
a = a + b | নতুন অবজেক্ট ✓ | নতুন লিস্ট ✓ (only list) | নতুন অবজেক্ট ✓ (3.9+ | ) |
a += b | নতুন অবজেক্ট (রি-অ্যাসাইন) | ইন-প্লেস এক্সটেন্ড ✓ (any iterable) | Error (ডিক্ট), |= ব্যবহার করুন (সেট) |
সেরা অনুশীলন: মিউটেবল অবজেক্টের জন্য ইন-প্লেস অপারেশন (+=, |=, .extend(), .update()) ব্যবহার করুন স্পষ্টতা এবং পারফরম্যান্সের জন্য।