🔆 جادوی init_subclass: جایگزین مدرن و تمیز برای Metaclassها
🔹 اکثر پایتونکارها برای مانیتور کردن، ثبت (Registration) یا ولیدیشن کلاسهای فرزندی که از یک کلاس به ارث میرسن، سراغ Metaclass میرن. اما متانویسی کد رو پیچیده، سنگین و خواناییش رو سخت میکنه.
🔹 از پایتون ۳.۶ به بعد، یک «تاس جادویی» به اسم init_subclass اضافه شد که ۹۰٪ نیازهای شما به متانویسی رو بدون هیچ پیچیدگی برطرف میکنه!
🔹 کاربرد واقعیش کجاست؟ (ساخت یک Plugin System خودکار)
🔹 فرض کنید میخواید هر وقت کلاسی از کلاس پایه شما ارثبری کرد، اسمش تلقائی توی یک دیکشنری ثبت بشه:
🔹به چه دردی میخوره؟
بدون ساخت Metaclass پیچیده، رفتارهای ارثبری رو مدیریت میکنید.
میتونید ورودیهای سفارشی (مثل plugin_name) مستقیماً موقع ارثبری کلاس بهش بدید.
کد کاملاً تمیز، خوانا و مطابق استاندارد روز پایتونه.
🐍 @python_rd
🔹 اکثر پایتونکارها برای مانیتور کردن، ثبت (Registration) یا ولیدیشن کلاسهای فرزندی که از یک کلاس به ارث میرسن، سراغ Metaclass میرن. اما متانویسی کد رو پیچیده، سنگین و خواناییش رو سخت میکنه.
🔹 از پایتون ۳.۶ به بعد، یک «تاس جادویی» به اسم init_subclass اضافه شد که ۹۰٪ نیازهای شما به متانویسی رو بدون هیچ پیچیدگی برطرف میکنه!
🔹 کاربرد واقعیش کجاست؟ (ساخت یک Plugin System خودکار)
🔹 فرض کنید میخواید هر وقت کلاسی از کلاس پایه شما ارثبری کرد، اسمش تلقائی توی یک دیکشنری ثبت بشه:
class BasePlugin:
plugins = {}
def __init_subclass__(cls, plugin_name: str = None, **kwargs):
super().__init_subclass__(**kwargs)
# اگر نام پلاگین مشخص نشده بود، از اسم خود کلاس استفاده کن
name = plugin_name or cls.__name__
cls.plugins[name] = cls
# حالا هر پلاگینی تعریف بشه، اتوماتیک ثبت میشه:
class AudioPlugin(BasePlugin, plugin_name="audio_player"):
pass
class VideoPlugin(BasePlugin, plugin_name="video_player"):
pass
print(BasePlugin.plugins)
# خروجی:
# {'audio_player': <class '__main__.AudioPlugin'>, 'video_player': <class '__main__.VideoPlugin'>}
🔹به چه دردی میخوره؟
بدون ساخت Metaclass پیچیده، رفتارهای ارثبری رو مدیریت میکنید.
میتونید ورودیهای سفارشی (مثل plugin_name) مستقیماً موقع ارثبری کلاس بهش بدید.
کد کاملاً تمیز، خوانا و مطابق استاندارد روز پایتونه.
🐍 @python_rd
👍1
🔆 چرا نباید از global توی پروژههای پایتونی استفاده کنیم؟
🔹 متغیرهای Global با اینکه کار رو سریع راه میاندازن، اما چالشهای بزرگی ایجاد میکنن:
سخت شدن دیباگ: هر تابعی میتونه متغیر رو تغییر بده و پیدا کردن منشأ ارور سخت میشه.
تستنویسی کابوسوار: تستهای ایزوله (Unit Tests) به مشکل میخورن.
🔹جایگزین: پاس دادن متغیرها به عنوان پارامتر ورودی تابع، یا استفاده از الگوریتمهای Object-Oriented و تزریق وابستگی (Dependency Injection).
🐍 @python_rd
🔹 متغیرهای Global با اینکه کار رو سریع راه میاندازن، اما چالشهای بزرگی ایجاد میکنن:
سخت شدن دیباگ: هر تابعی میتونه متغیر رو تغییر بده و پیدا کردن منشأ ارور سخت میشه.
تستنویسی کابوسوار: تستهای ایزوله (Unit Tests) به مشکل میخورن.
🔹جایگزین: پاس دادن متغیرها به عنوان پارامتر ورودی تابع، یا استفاده از الگوریتمهای Object-Oriented و تزریق وابستگی (Dependency Injection).
🐍 @python_rd
❤5👍1
🔆 اجرای فرآیند پسزمینه بدون بلاک شدن برنامه با iter() دو آرگومانهای!
🔹 مفهوم: همه با شکل معمولی iter(iterable) آشنا هستیم. اما کمتر کسی میدونه که iter() یک فرم دو آرگومانهای به شکل iter(callable, sentinel) داره!
🔹 کاربرد واقعی: خواندن فایلهای حجیم یا Stream دیتابیس/شبکه تکهتکه (Chunk) تا زمانی که به یک مقدار خاص (Sentinel) برسی، بدون نیاز به نوشتن حلقه while True و شرطهای اضافه!
🔹 به چه دردی میخوره؟
کد فوقالعاده تمیز، پایتونیک و بدون نیاز به تعریف متغیرهای موقت درون حلقه میشه.
🐍 @python_rd
🔹 مفهوم: همه با شکل معمولی iter(iterable) آشنا هستیم. اما کمتر کسی میدونه که iter() یک فرم دو آرگومانهای به شکل iter(callable, sentinel) داره!
🔹 کاربرد واقعی: خواندن فایلهای حجیم یا Stream دیتابیس/شبکه تکهتکه (Chunk) تا زمانی که به یک مقدار خاص (Sentinel) برسی، بدون نیاز به نوشتن حلقه while True و شرطهای اضافه!
# خواندن یک فایل خطبهخط یا بلوکی تا رسیدن به خط خالی:
with open('data.txt', 'r') as f:
# حلقه تا زمانی ادامه پیدا میکنه که خروجی f.readline برابر '' (خط خالی) بشه
for line in iter(f.readline, ''):
process(line.strip())
🔹 به چه دردی میخوره؟
کد فوقالعاده تمیز، پایتونیک و بدون نیاز به تعریف متغیرهای موقت درون حلقه میشه.
🐍 @python_rd
🔆 فایل pip.conf؛ امن کردن Pip جلوی حملات Supply Chain!
🔹 خیلی وقتها توی پروژهها پکیجهای شخصی یا سازمانی نصب میکنیم. حملهای به اسم Dependency Confusion وجود داره که اگر نام پکیج داخلی شما با یک پکیج عمومی روی PyPI یکی باشه، Pip ممکنه نسخه مخرب عمومی رو دانلود کنه!
🔹 راه حل: ایجاد یک فایل کانفیگ اختصاصی برای Pip تا اولویت دانلود رو فقط روی مخزن امن تنظیم کنه:
🔹 به چه دردی میخوره؟
با اضافه کردن require-hashes = true حتی اگر کسی پکیجی روی PyPI رو هک کنه و تغییر بده، تا زمانی که Hash اون تغییر نکرده باشه Pip اجازه نصب نمیده. این نکته برای کسانی که پروژه واقعی و تجاری میزنن عالیه.
🐍 @python_rd
🔹 خیلی وقتها توی پروژهها پکیجهای شخصی یا سازمانی نصب میکنیم. حملهای به اسم Dependency Confusion وجود داره که اگر نام پکیج داخلی شما با یک پکیج عمومی روی PyPI یکی باشه، Pip ممکنه نسخه مخرب عمومی رو دانلود کنه!
🔹 راه حل: ایجاد یک فایل کانفیگ اختصاصی برای Pip تا اولویت دانلود رو فقط روی مخزن امن تنظیم کنه:
# مسیر فایل: ~/.config/pip/pip.conf
[global]
index-url = https://your-private-repo.com/simple
extra-index-url = https://pypi.org/simple
require-hashes = true
🔹 به چه دردی میخوره؟
با اضافه کردن require-hashes = true حتی اگر کسی پکیجی روی PyPI رو هک کنه و تغییر بده، تا زمانی که Hash اون تغییر نکرده باشه Pip اجازه نصب نمیده. این نکته برای کسانی که پروژه واقعی و تجاری میزنن عالیه.
🐍 @python_rd
🔆 تکنیک ناشناخته و حرفهای functools.singledispatch (اورلود کردن توابع در پایتون بدون if/elseهای طولانی!)
🔹 چطوری تو پایتون تابع Overloading تمیز بنویسیم؟
خیلی وقتها پیش میاد که میخوایم یه تابع بستگی به اینکه چه جنس ورودیای (String, List, Dict...) بهش میدیم، رفتار متفاوتی داشته باشه. روش مبتدیانه چیه؟ نوشتن یه سلسله if isinstance(...) طولانی!
اما روش سینیورها توی پایتون استفاده از singledispatch از کتابخونه استاندارد functools هست.
🔹به چه دردی میخوره؟
کد بسیار کپسوله، خلوت و خوانا میشه.
اصل Open/Closed رعایت میشه (میتونی بعداً بدون دست زدن به تابع اصلی، تایپ جدید اضافه کنی).
🐍 @python_rd
🔹 چطوری تو پایتون تابع Overloading تمیز بنویسیم؟
خیلی وقتها پیش میاد که میخوایم یه تابع بستگی به اینکه چه جنس ورودیای (String, List, Dict...) بهش میدیم، رفتار متفاوتی داشته باشه. روش مبتدیانه چیه؟ نوشتن یه سلسله if isinstance(...) طولانی!
اما روش سینیورها توی پایتون استفاده از singledispatch از کتابخونه استاندارد functools هست.
from functools import singledispatch
@singledispatch
def process_data(data):
raise NotImplementedError("این تایپ پشتیبانی نمیشه!")
@process_data.register(str)
def _(data):
return f"متن پردازش شد: {data.upper()}"
@process_data.register(list)
def _(data):
return f"لیست پردازش شد با طول: {len(data)}"
@process_data.register(dict)
def _(data):
return f"کلیدهای دیکشنری: {list(data.keys())}"
# تست تابع
print(process_data("hello")) # متن پردازش شد: HELLO
print(process_data([1, 2, 3])) # لیست پردازش شد با طول: 3
🔹به چه دردی میخوره؟
کد بسیار کپسوله، خلوت و خوانا میشه.
اصل Open/Closed رعایت میشه (میتونی بعداً بدون دست زدن به تابع اصلی، تایپ جدید اضافه کنی).
🐍 @python_rd
👍2
🔆 مجموعهای از نکات و تقلبنامههایی برای زبان برنامهنویسی پایتون
🔹https://gto76.github.io/python-cheatsheet
🐍 @python_rd
🔹https://gto76.github.io/python-cheatsheet
🐍 @python_rd
gto76.github.io
Comprehensive Python Cheatsheet
Exhaustive, simple, beautiful and concise. A truly Pythonic cheat sheet about Python programming language.
❤1
🔆 نکات کلیدی برای تمیزتر کد زدن در پایتون و چندزبان دیگر
🔹github.com/zedr/clean-code-python
🔹github.com/jupeter/clean-code-php
🔹github.com/ryanmcdermott/clean-code-javascript
🔹github.com/thangchung/clean-code-dotnet
🔹github.com/labs42io/clean-code-typescript
🐍 @python_rd
🔹github.com/zedr/clean-code-python
🔹github.com/jupeter/clean-code-php
🔹github.com/ryanmcdermott/clean-code-javascript
🔹github.com/thangchung/clean-code-dotnet
🔹github.com/labs42io/clean-code-typescript
🐍 @python_rd
🔆 مدیریت منابع با contextlib
🔹 از تکرار try...finally برای بستن فایلها و اتصالها خسته شدی؟
🔹 پایتون ابزاری به نام Context Manager داره که با دستور with استفاده میشه. اما اگر بخوای خودت یک Context Manager سفارشی بسازی، نیازی نیست حتماً کلاس با متدهای enter و exit بنویسی!
با ماژول contextlib و دکوراتور @contextmanager میتونی خیلی تمیز این کار رو انجام بدی:
🐍 @python_rd
🔹 از تکرار try...finally برای بستن فایلها و اتصالها خسته شدی؟
🔹 پایتون ابزاری به نام Context Manager داره که با دستور with استفاده میشه. اما اگر بخوای خودت یک Context Manager سفارشی بسازی، نیازی نیست حتماً کلاس با متدهای enter و exit بنویسی!
با ماژول contextlib و دکوراتور @contextmanager میتونی خیلی تمیز این کار رو انجام بدی:
from contextlib import contextmanager
@contextmanager
def managed_resource():
print("-> باز کردن اتصال/فایل")
yield "Resource Object"
print("-> بستن ایمن اتصال/فایل")
# استفاده:
with managed_resource() as res:
print(f"در حال کار با: {res}")
🐍 @python_rd
🔆 خروجی این تکه کد چیه؟
🔹گزینهها:
الف) [1], [2], [9, 9, 3], [4]
ب) [1], [1, 2], [9, 9, 3], [1, 2, 4]
ج) [1], [2], [3], [4]
🐍 @python_rd
def add_item(item, lst=[]):
lst.append(item)
return lst
print(add_item(1))
print(add_item(2))
print(add_item(3, [9, 9]))
print(add_item(4))
🔹گزینهها:
الف) [1], [2], [9, 9, 3], [4]
ب) [1], [1, 2], [9, 9, 3], [1, 2, 4]
ج) [1], [2], [3], [4]
🐍 @python_rd
🔆 چرا برای دادههای حجیم نباید از return استفاده کنی؟
🔹 وقتی یک تابع لیست بزرگی از دادهها رو با return برمیگرداند، کل دادهها باید همزمان توی رم (RAM) لود بشن که باعث مصرف شدید حافظه و کندی سیستم میشه.
🔹 اما اگر به جای return از yield استفاده کنی، تابع تبدیل به یک Generator میشه که دادهها رو به صورت تکبهتک و تنبل (Lazy Evaluation) تولید میکنه:
🔹با این روش میتونی فایلهای چند گیگابایتی رو با مصرف چند مگابایت رم پردازش کنی!
🐍 @python_rd
🔹 وقتی یک تابع لیست بزرگی از دادهها رو با return برمیگرداند، کل دادهها باید همزمان توی رم (RAM) لود بشن که باعث مصرف شدید حافظه و کندی سیستم میشه.
🔹 اما اگر به جای return از yield استفاده کنی، تابع تبدیل به یک Generator میشه که دادهها رو به صورت تکبهتک و تنبل (Lazy Evaluation) تولید میکنه:
def read_large_file(file_path):
with open(file_path, 'r') as f:
for line in f:
yield line.strip() # هر بار فقط یک خط را در حافظه نگه میدارد
🔹با این روش میتونی فایلهای چند گیگابایتی رو با مصرف چند مگابایت رم پردازش کنی!
🐍 @python_rd
🔆 مدیریت تمیز منابع با Context Managerهای سفارشی (contextlib)
🔹 ساخت Context Managerها معمولاً با نوشتن کلاس و متدهای enter و exit انجام میشود. اما با دکوراتور contextmanager@ از ماژول contextlib میتوانید این کار را خیلی سریعتر و پایتونیکتر انجام دهید.
🐍 @python_rd
🔹 ساخت Context Managerها معمولاً با نوشتن کلاس و متدهای enter و exit انجام میشود. اما با دکوراتور contextmanager@ از ماژول contextlib میتوانید این کار را خیلی سریعتر و پایتونیکتر انجام دهید.
from contextlib import contextmanager
import time
@contextmanager
def measure_time(task_name: str):
start_time = time.perf_counter()
print(f"--- شروع: {task_name} ---")
try:
yield # کنترل اجرا در این نقطه به بدنه with منتقل میشود
finally:
elapsed = time.perf_counter() - start_time
print(f"--- پایان: {task_name} | زمان اجرا: {elapsed:.4f} ثانیه ---\n")
# استفاده کاربردی
with measure_time("پردازش سنگین دادهها"):
# شبیهسازی یک کار سنگین
total = sum(i**2 for i in range(10_000_000))
print(f"نتیجه محاسبات: {total}")
🐍 @python_rd
🔆 حذف تاریخی GIL از پایتون (Free-threaded Python)
🔹 یک رویداد تاریخی: حذف قفل مفسر (GIL) از هسته CPython رسماً کلید خورد!
🔹 سرانجام پس از سالها بحث و مناظره در بنیاد نرمافزار پایتون (PSF)، طرح PEP 703 (معروف به Free-threaded CPython) تصویب و گامهای اجرایی آن آغاز شد. با این تغییر، مفسر پایتون میتواند از تمام هستههای پردازنده (Multi-Core CPU) در Multi-threading به صورت واقعی بهره ببرد بدون اینکه گلوگاه قفل مفسر سر راهش باشد.
🔹 نکات کلیدی این تحول:
▪️ پشتیبانی اولیه به صورت بیلد آزمایشی (Experimental /
▪️ تیمهای توسعه کتابخانههای بزرگ مانند NumPy و PyTorch در حال بازنویسی بخشهای C-API خود برای سازگاری با حالت بدون GIL هستند.
▪️ طبق پیشبینی هسته مرکزی، پایتون در پردازشهای سنگین موازی تا چند برابر افزایش کارایی را تجربه خواهد کرد.
🔹 منبع رسمی:
• مستندات رسمی PEP 703: peps.python.org/pep-0703
• اعلامیه Steering Council پایتون: discuss.python.org
🐍 @python_rd
🔹 یک رویداد تاریخی: حذف قفل مفسر (GIL) از هسته CPython رسماً کلید خورد!
🔹 سرانجام پس از سالها بحث و مناظره در بنیاد نرمافزار پایتون (PSF)، طرح PEP 703 (معروف به Free-threaded CPython) تصویب و گامهای اجرایی آن آغاز شد. با این تغییر، مفسر پایتون میتواند از تمام هستههای پردازنده (Multi-Core CPU) در Multi-threading به صورت واقعی بهره ببرد بدون اینکه گلوگاه قفل مفسر سر راهش باشد.
🔹 نکات کلیدی این تحول:
▪️ پشتیبانی اولیه به صورت بیلد آزمایشی (Experimental /
--disable-gil) در دسترس قرار گرفته است.▪️ تیمهای توسعه کتابخانههای بزرگ مانند NumPy و PyTorch در حال بازنویسی بخشهای C-API خود برای سازگاری با حالت بدون GIL هستند.
▪️ طبق پیشبینی هسته مرکزی، پایتون در پردازشهای سنگین موازی تا چند برابر افزایش کارایی را تجربه خواهد کرد.
🔹 منبع رسمی:
• مستندات رسمی PEP 703: peps.python.org/pep-0703
• اعلامیه Steering Council پایتون: discuss.python.org
🐍 @python_rd
Python Enhancement Proposals (PEPs)
PEP 703 – Making the Global Interpreter Lock Optional in CPython | peps.python.org
CPython’s global interpreter lock (“GIL”) prevents multiple threads from executing Python code at the same time. The GIL is an obstacle to using multi-core CPUs from Python efficiently. This PEP proposes adding a build configuration (--disable-gil) to...
🔆 راز مکانیزم پیادهسازی و تغییر جهت
🔹 باگ ریاضیاتی پنهان: چرا پایتون هیچوقت نمیتواند لیستی از NaNها را مرتب کند؟!
🔹 در پایتون، مقدار
nan طبق استاندارد IEEE-754 با خودش هم برابر نیست!
🔹 حالا شگفتی ماجرا در متد
الگوریتم مرتبسازی CPython یعنی Timsort بر اصل تقارن و ترتیبی بودن مقایسهها استوار است. اگر شما لیستی شامل اعداد و NaN را با
🔹 نتیجه خروجی به ترتیب قرارگیری اولیه عناصر بستگی دارد و غیرقابلپیشبینی است!
🔹 پایتون هیچ خطایی (Error) raise نمیکند، اما خروجی نهایی مرتبشده نخواهد بود!
🔹 مهندسان CPython سالهاست که در گیتهاب پایتون روی این موضوع بحث دارند و تصمیم گرفتهاند برای حفظ پرفورمنس Timsort، هیچ لایه اعتبارسنجی اضافی اضافه نکنند و این مسئولیت را روی دوش برنامهنویس بگذارند!
🐍@python_rd
NaN در الگوریتم مرتبسازی پایتون (Timsort)🔹 باگ ریاضیاتی پنهان: چرا پایتون هیچوقت نمیتواند لیستی از NaNها را مرتب کند؟!
🔹 در پایتون، مقدار
float('nan') (Not a Number) خصوصیت عجیبی دارد:nan طبق استاندارد IEEE-754 با خودش هم برابر نیست!
float('nan') == float('nan') ⬅️ خروجی False است!float('nan') < 5 ⬅️ باز هم False است!🔹 حالا شگفتی ماجرا در متد
.sort() پایتون است:الگوریتم مرتبسازی CPython یعنی Timsort بر اصل تقارن و ترتیبی بودن مقایسهها استوار است. اگر شما لیستی شامل اعداد و NaN را با
.sort() مرتب کنید:🔹 نتیجه خروجی به ترتیب قرارگیری اولیه عناصر بستگی دارد و غیرقابلپیشبینی است!
🔹 پایتون هیچ خطایی (Error) raise نمیکند، اما خروجی نهایی مرتبشده نخواهد بود!
🔹 مهندسان CPython سالهاست که در گیتهاب پایتون روی این موضوع بحث دارند و تصمیم گرفتهاند برای حفظ پرفورمنس Timsort، هیچ لایه اعتبارسنجی اضافی اضافه نکنند و این مسئولیت را روی دوش برنامهنویس بگذارند!
🐍@python_rd
کوییز پایتون
🔆 خروجی اجرای کد زیر چیست؟
🔹 گزینهها:
1️⃣
2️⃣
3️⃣ خطای مدیریتنشده رخ میدهد و برنامه متوقف میشود
4️⃣ خروجی
🐍@python_rd
🔆 خروجی اجرای کد زیر چیست؟
t = (1, 2, [3, 4])
try:
t[2] += [5]
except TypeError:
pass
print(t)
🔹 گزینهها:
1️⃣
(1, 2, [3, 4])2️⃣
(1, 2, [3, 4, 5])3️⃣ خطای مدیریتنشده رخ میدهد و برنامه متوقف میشود
4️⃣ خروجی
(1, 2, [5]) خواهد بود🐍@python_rd
🔆 یک تله عجیب در پایتون:
🔹 خیلیها میدانند
🔹 این یعنی:
در سطح type system، از
🔹 این رفتار در خیلی از سناریوها مفید است، ولی اگر روی counting، hashing یا data processing کار کنی، گاهی میتواند نتایج عجیبی بسازد.
🐍 @python_rd
bool در واقع زیرکلاس int است🔹 خیلیها میدانند
True == 1 و False == 0، اما نکته عجیبتر اینجاست که:print(isinstance(True, int)) # True
print(True + True) # 2
print(False + 10) # 10
🔹 این یعنی:
True و False فقط مقدار بولی نیستنددر سطح type system، از
int ارثبری میکنند🔹 این رفتار در خیلی از سناریوها مفید است، ولی اگر روی counting، hashing یا data processing کار کنی، گاهی میتواند نتایج عجیبی بسازد.
🐍 @python_rd
❤4
🔆 آیا
🔹 خیلیها هنوز این شکلی مینویسند:
🔹 ولی راه پایتونیکتر:
🔹 اگر index را از 1 بخواهی:
🔹 چرا بهتر است؟
خواناتر است
خطای index کمتر میشود
پایتونیکتر و حرفهایتر است
🔹 این از آن تفاوتهای کوچک است که کیفیت کد را در بلندمدت خیلی بالا میبرد.
🐍 @python_rd
enumerate() بهتر از index-based loop است؟🔹 خیلیها هنوز این شکلی مینویسند:
items = ["apple", "banana", "orange"]
for i in range(len(items)):
print(i, items[i])
🔹 ولی راه پایتونیکتر:
items = ["apple", "banana", "orange"]
for index, value in enumerate(items):
print(index, value)
🔹 اگر index را از 1 بخواهی:
for index, value in enumerate(items, start=1):
print(index, value)
🔹 چرا بهتر است؟
خواناتر است
خطای index کمتر میشود
پایتونیکتر و حرفهایتر است
🔹 این از آن تفاوتهای کوچک است که کیفیت کد را در بلندمدت خیلی بالا میبرد.
🐍 @python_rd
🌐 خروجی این کد پایتون چیست؟
🔹 گزینهها:
🔹A)
[1, 2, 3, 4, 5]
[1, 2, 3]
🔹B)
[1, 2, 3, 4, 5]
[1, 2, 3, 4, 5]
🔹C)
Error
🔹D)
[4, 5]
[1, 2, 3]
🐍 @python_rd
x = [1, 2, 3]
y = x
x += [4, 5]
print(x)
print(y)
🔹 گزینهها:
🔹A)
[1, 2, 3, 4, 5]
[1, 2, 3]
🔹B)
[1, 2, 3, 4, 5]
[1, 2, 3, 4, 5]
🔹C)
Error
🔹D)
[4, 5]
[1, 2, 3]
🐍 @python_rd