چالش روزانه · ۲۲ مهر ۱۴۰۵

چالش پایتون ۱: += روی لیست؛ تغییر یا ساختن؟

قبل از اجرای کد، خروجی آن را پیش‌بینی کن. حدس نزن؛ خط به خط فکر کن پایتون چه می‌کند.

a = [1, 2, 3]
b = a
b += [4]
b = b + [5]
print(a, b)
خروجی کدام است؟

نمایش پاسخ و توضیح

پاسخ درست: گزینهٔ ب — [1, 2, 3, 4] [1, 2, 3, 4, 5]

خط به خط

  1. a = [1, 2, 3] یک لیست می‌سازد و نام a را به آن می‌چسباند.
  2. b = a لیست جدید نمی‌سازد؛ فقط نام دوم b را به همان لیست می‌چسباند. حالا یک شیء داریم با دو اسم.
  3. b += [4] برای لیست‌ها درجا (in-place) کار می‌کند: پایتون متد __iadd__ را صدا می‌زند که عملاً همان extend است. پس خود لیست مشترک عوض می‌شود و a هم [1, 2, 3, 4] را می‌بیند.
  4. b = b + [5] فرق دارد: عملگر + همیشه یک لیست جدید می‌سازد و بعد b به آن لیست تازه چسبانده می‌شود. از این لحظه a و b دیگر یک شیء نیستند.

پس a می‌ماند [1, 2, 3, 4] و b می‌شود [1, 2, 3, 4, 5].

با id ببینید

تابع id() شناسهٔ هر شیء را برمی‌گرداند. اگر دو نام id یکسان داشته باشند، یعنی به یک شیء اشاره می‌کنند:

a = [1, 2, 3]
b = a
print(a is b)        # True
b += [4]
print(a is b)        # هنوز True — همان لیست تغییر کرد
b = b + [5]
print(a is b)        # False — b حالا لیست جدیدی است

نکتهٔ امتحانی

  • برای انواع تغییرپذیر (list، dict، set)، x += y معمولاً درجاست؛ ولی x = x + y شیء جدید می‌سازد.
  • برای انواع تغییرناپذیر (int، str، tuple) هر دو شکل شیء جدید می‌سازند، چون اصلاً نمی‌شود خودشان را تغییر داد.
  • اگر واقعاً کپی مستقل می‌خواهید: b = a.copy() یا b = a[:].

حالا خودت اجرا کن و تغییرش بده

a = [1, 2, 3]
b = a
b += [4]
b = b + [5]
print(a, b)