امروز، ۱۷ مهر ۱۴۰۵ (۹ اکتبر ۲۰۲۶) ، نسخه نهایی پایتون 3.15 منتشر شد. این بار انتشار یک هفته عقب افتاد، چون تیم پایتون چند باگ دقیقه نودی در مهم‌ترین قابلیت این نسخه پیدا کرد و ترجیح داد یک نسخه کاندید (Release Candidate) دیگر هم بدهد. به نظرم ارزش صبر کردن را داشت. پایتون 3.15 از آن نسخه‌هایی است که فقط چند تابع جدید به کتابخانه‌ها اضافه نمی‌کند؛ چند تغییر در خود زبان دارد که احتمالاً از همین سال در کدهای روزمره‌مان می‌بینیم.

در این نوشته مهم‌ترین ویژگی‌های جدید را به زبان ساده مرور می‌کنم. فرضم این است که پایتون را می‌شناسید و با لیست، دیکشنری، تابع و import راحتید؛ لازم نیست متخصص باشید. برای هر ویژگی یک مثال کوتاه هم گذاشته‌ام که خودتان امتحانش کنید.

پایتون 3.15 منتشر شد؛ ویژگی‌های جدید به زبان ساده فهرست ویژگی‌های جدید پایتون 3.15: lazy import، frozendict، sentinel، UTF 8 پیش‌فرض و پروفایلر جدید
نقشه کلی تازه‌های پایتون 3.15

ایمپورت تنبل در پایتون 3.15؛ برنامه‌هایی که سریع‌تر بالا می‌آیند

ستاره این نسخه بدون شک ایمپورت تنبل (Lazy Import) است که در PEP 810 تعریف شده. مشکلی که حل می‌کند را احتمالاً تجربه کرده‌اید: بالای فایل ده‌ها ماژول را import می‌کنید و پایتون همه را همان لحظه اجرا بارگذاری می‌کند، حتی آن‌هایی که شاید در این اجرا اصلاً لازم نشوند. نتیجه‌اش ابزارهای خط فرمانی (CLI) است که فقط برای نشان دادن --help یک ثانیه فکر می‌کنند.

حالا با کلمه کلیدی lazy می‌گویید «این ماژول را فعلاً بارگذاری نکن، هر وقت واقعاً لازمش داشتم بیاورش» :

پایتون 3.15 منتشر شد؛ ویژگی‌های جدید به زبان ساده نمونه کد lazy import، frozendict و sentinel در پایتون 3.15
سه ویژگی تازه زبان در چند خط
lazy import json
lazy from pathlib import Path

print("Starting up...")              # json هنوز بارگذاری نشده
data = json.loads('{"lang": "fa"}')  # همین‌جا بارگذاری می‌شود

چند نکته که باید بدانید:

  • lazy یک «کلمه کلیدی نرم» (Soft Keyword) است؛ یعنی اگر جایی در کدتان متغیری به اسم lazy دارید، چیزی خراب نمی‌شود.
  • فقط در سطح ماژول (بالای فایل) مجاز است، نه داخل تابع یا کلاس.
  • اگر بخواهید همه ایمپورت‌های یک برنامه تنبل شوند، بدون دست زدن به کد می‌توانید با -X lazy_imports=all یا متغیر محیطی PYTHON_LAZY_IMPORTS اجرایش کنید. این برای تست کردن برنامه‌های بزرگ خیلی به درد می‌خورد.

یک هشدار کوچک: ماژول‌هایی که موقع import «کاری انجام می‌دهند» (مثلاً چیزی را ثبت می‌کنند یا تنظیماتی را عوض می‌کنند) ، با lazy دیرتر آن کار را انجام می‌دهند. پس اول روی کتابخانه‌های سنگین و بی‌دردسر امتحانش کنید.

frozendict؛ دیکشنری‌ای که عوض نمی‌شود

سال‌ها برای یک دیکشنری غیرقابل‌تغییر (Immutable) یا باید سراغ types.MappingProxyType می‌رفتیم یا یک کتابخانه جانبی نصب می‌کردیم. در پایتون 3.15 نوع داخلی frozendict اضافه شده (PEP 814)؛ همان رابطه‌ای که frozenset با set دارد، حالا frozendict با dict دارد:

>>> settings = frozendict(debug=False, port=8000)
>>> settings["port"] = 9000
TypeError: 'frozendict' object does not support item assignment
>>> settings == frozendict(port=8000, debug=False)
True

چون تغییر نمی‌کند، «هش‌پذیر» (Hashable) است؛ یعنی می‌توانید آن را کلید یک دیکشنری دیگر کنید یا داخل set بگذارید. برای تنظیمات ثابت برنامه، مقادیر پیش‌فرض توابع و کش کردن نتیجه‌ها خیلی تمیزتر از قبل است. فقط یادتان باشد که frozendict زیرکلاس dict نیست، پس isinstance(x, dict) برایش False برمی‌گرداند.

sentinel؛ خداحافظی با object() های بی‌نام

این یکی را کسانی که کتابخانه می‌نویسند خیلی دوست خواهند داشت. فرض کنید تابعی دارید که پارامتر default می‌گیرد و None هم یک مقدار معتبر برای آن است. چطور بفهمید کاربر اصلاً چیزی نفرستاده؟ راه قدیمی ساختن یک object() خالی بود که در خروجی و پیام خطا شکل زشتی مثل <object object at 0x7f...> داشت. حالا تابع داخلی sentinel (PEP 661) را داریم:

MISSING = sentinel("MISSING")

def get_setting(key, default=MISSING):
    if default is MISSING:
        ...  # کاربر مقدار پیش‌فرض نداده

print(MISSING)   # MISSING

اسمش خواناست، با pickle و copy هویتش را حفظ می‌کند و ابزارهای بررسی نوع (Type Checker) هم آن را می‌فهمند. فقط همیشه با is مقایسه‌اش کنید، چون برخلاف None مقدار بولی‌اش True است.

باز کردن لیست‌ها داخل Comprehension

یک تغییر کوچک ولی دلنشین (PEP 798): حالا می‌توانید از * و ** مستقیماً داخل Comprehension استفاده کنید. صاف کردن (Flatten) یک لیست تودرتو یا ادغام چند دیکشنری دیگر به حلقه تودرتو یا itertools.chain نیاز ندارد:

>>> lists = [[1, 2], [3, 4], [5]]
>>> [*L for L in lists]
[1, 2, 3, 4, 5]
>>> dicts = [{"a": 1}, {"b": 2}, {"a": 3}]
>>> {**d for d in dicts}
{'a': 3, 'b': 2}

UTF-8 بالاخره پیش‌فرض شد؛ خبر خوب برای ما فارسی‌زبان‌ها

اگر روی ویندوز با فایل‌های فارسی کار کرده باشید، حتماً با UnicodeDecodeError یا متن‌های به‌هم‌ریخته روبه‌رو شده‌اید. دلیلش این بود که open() بدون آرگومان encoding، از کدگذاری پیش‌فرض سیستم‌عامل استفاده می‌کرد که روی ویندوزهای فارسی معمولاً cp1256 بود، نه UTF-8. همین باعث می‌شد کدی که روی لینوکس سالم کار می‌کرد، روی ویندوز همکارتان خطا بدهد.

از پایتون 3.15 طبق PEP 686 حالت UTF-8 به‌صورت پیش‌فرض روشن است و open() بدون تعیین encoding، فایل را UTF-8 می‌خواند و می‌نویسد. اگر برنامه قدیمی‌ای دارید که به رفتار قبلی وابسته است، با PYTHONUTF8=0 یا -X utf8=0 برش می‌گردانید. ولی توصیه من همان توصیه همیشگی است: encoding="utf-8" را صریح بنویسید تا کدتان روی نسخه‌های قدیمی‌تر هم درست کار کند.

پیام‌های خطای مهربان‌تر

پایتون چند نسخه است که روی پیام‌های خطا وقت می‌گذارد و این نسخه هم ادامه همان مسیر است. مخصوصاً برای کسانی که از زبان‌های دیگر مثل جاوااسکریپت یا جاوا آمده‌اند، این پیام‌ها خیلی کمک می‌کنند:

>>> [1, 2, 3].push(4)
AttributeError: 'list' object has no attribute 'push'. Did you mean '.append'?
>>> {}.put("a", 1)
AttributeError: 'dict' object has no attribute 'put'. Use d[k] = v.

به‌علاوه argparse حالا به‌صورت پیش‌فرض وقتی کاربر یک گزینه را اشتباه تایپ کند، گزینه درست را پیشنهاد می‌دهد.

Tachyon؛ پروفایلری که برنامه را کند نمی‌کند

ابزارهای پروفایل (Profiling) حالا زیر یک بسته جدید به اسم profiling جمع شده‌اند. cProfile قدیمی سر جایش هست، ولی ستاره ماجرا یک پروفایلر نمونه‌برداری (Sampling Profiler) به اسم Tachyon است. فرقش این است که به‌جای ثبت تک‌تک فراخوانی‌ها، مدام از برنامه «عکس» می‌گیرد؛ پس سربار (Overhead) خیلی کمی دارد و حتی می‌تواند به یک برنامه در حال اجرا با شماره پروسه (PID) وصل شود:

python -m profiling.sampling run --flamegraph -o profile.html script.py
python -m profiling.sampling attach 12345

خروجی دستور اول یک فلیم‌گراف (Flame Graph) HTML است که در مرورگر باز می‌کنید و می‌بینید وقت برنامه دقیقاً کجا صرف می‌شود. برای سرورهای وب، ربات‌ها و اسکریپت‌هایی که «یک‌جایی کند می‌شوند» ، این ابزار واقعاً نجات‌دهنده است.

سرعت؛ JIT بالغ‌تر شده

کامپایلر JIT که از پایتون 3.13 به‌صورت آزمایشی آمده بود، در این نسخه حسابی بازنویسی و بهتر شده. طبق اعداد رسمی، روی لینوکس x86-64 به‌طور میانگین حدود ۷ تا ۸ درصد و روی مک‌های اپل سیلیکون حدود ۱۱ تا ۱۲ درصد سریع‌تر از مفسر معمولی است. عدد انقلابی‌ای نیست و JIT هنوز آزمایشی است، ولی جهت حرکت روشن است. جدا از JIT، چند جای کتابخانه استاندارد هم سریع‌تر شده؛ مثلاً کدگذاری Base64 حدود دو برابر و کدگشایی‌اش حدود سه برابر سریع‌تر شده است.

تغییرات کوچک‌تر ولی به‌دردبخور

  • math.integer: توابع مخصوص اعداد صحیح مثل gcd، lcm، isqrt، comb و factorial یک خانه مرتب و جدید در ماژول math.integer دارند.
  • TOML 1.1: tomllib حالا از TOML 1.1 پشتیبانی می‌کند؛ مثلاً کامای اضافه آخر و شکستن خط در جدول‌های درون‌خطی مجاز شده.
  • re.prefixmatch(): اسمی شفاف‌تر برای re.match() که همیشه تازه‌کارها را گیج می‌کرد، چون فقط ابتدای رشته را بررسی می‌کند. match حذف نمی‌شود، فقط «نرم» منسوخ شده.
  • تایپینگ: TypedDict حالا می‌تواند با closed=True بسته باشد یا با extra_items نوع کلیدهای اضافه را مشخص کند، و TypeForm هم برای کتابخانه‌هایی مثل Pydantic که با خود «نوع‌ها» کار می‌کنند اضافه شده.
  • یونیکد 17: ماژول unicodedata به یونیکد 17 به‌روز شده و تابع‌هایی مثل iter_graphemes() دارد که برای کار درست با ایموجی‌ها و حروف ترکیبی مفید است.

قبل از ارتقا به پایتون 3.15 چه چیزهایی را چک کنیم؟

هر نسخه جدید چیزهایی را هم حذف می‌کند. مهم‌ترین‌هایی که ممکن است به کد شما بخورند:

  • ماژول profile (نسخه پایتونی خالص، نه cProfile) منسوخ شده و در 3.17 حذف می‌شود.
  • سیستم Event Loop Policy در asyncio منسوخ شده؛ به‌جایش از asyncio.run(main(), loop_factory=...) استفاده کنید.
  • چیزهای قدیمی‌ای مثل CGIHTTPRequestHandler، PurePath.is_reserved()، glob.glob0() و glob.glob1() و ساختن NamedTuple با آرگومان‌های کلیدواژه‌ای حذف شده‌اند.
  • اگر روی ویندوز فایل غیر UTF-8 بدون تعیین encoding می‌خوانید، حالا رفتار عوض شده (بخش UTF-8 را ببینید) .

توصیه شخصی من: پروژه‌های جدید را از همین حالا با پایتون 3.15 شروع کنید، ولی برای پروژه‌های در حال اجرا چند هفته صبر کنید تا کتابخانه‌هایی که استفاده می‌کنید (مخصوصاً آن‌هایی که بخش C دارند، مثل NumPy) نسخه سازگارشان را منتشر کنند. فهرست کامل تغییرات در صفحه What’s New in Python 3.15 در مستندات رسمی پایتون آمده است.

یادگیری پایتون در رشت؛ دوره‌های پایتون کادوس

اگر این مقاله را خواندید و حس کردید بعضی مفاهیمش هنوز برایتان جا نیفتاده، یا دوست دارید پایتون را اصولی و از پایه یاد بگیرید، یک پیشنهاد نزدیک دارم. همان‌طور که قبلاً نوشته بودم، مسئولیت دپارتمان کامپیوتر و فناوری اطلاعات مؤسسه آموزشی کادوس رشت با من است و یکی از دغدغه‌هایم این بوده که برنامه‌نویسی در گیلان را جدی و به‌روز آموزش بدهیم. در این نوشته هم گفته بودم چرا فکر می‌کنم برنامه‌نویسی یکی از بهترین مهارت‌ها برای جوان‌های رشت و گیلان است.

دوره‌های پایتون کادوس به‌صورت حضوری و آنلاین برگزار می‌شوند:

  • پایتون مقدماتی: ۴۰ جلسه، برای کسی که تا حالا برنامه‌نویسی نکرده و فقط با کامپیوتر و ویندوز آشناست. از متغیر و شرط و حلقه تا تابع، لیست و دیکشنری، کار با فایل، مقدمات شیءگرایی و محیط مجازی (Virtual Environment) .
  • پایتون پیشرفته: ۴۰ جلسه ۹۰ دقیقه‌ای برای کسی که مقدمات را بلد است. شیءگرایی جدی، NumPy و Pandas و Matplotlib، کار با فایل‌های CSV و Excel و JSON، پایگاه داده (SQLite و MySQL) ، رابط گرافیکی با Tkinter، کار با API و خودکارسازی کارهای تکراری با پروژه‌های عملی.
  • FastAPI: و اگر پایتون را خوب بلدید و می‌خواهید وارد بک‌اند شوید، اولین دوره FastAPI در رشت و گیلان را هم همین چند روز پیش در کادوس شروع کردیم.

برای مشاوره، زمان‌بندی کلاس‌ها و ثبت‌نام می‌توانید به شعبه مرکزی کادوس در خیابان لاکانی رشت سر بزنید یا با شماره ۰۱۳۹۱۰۰۲۳۴۳ تماس بگیرید. اگر هم مطمئن نیستید از کدام دوره شروع کنید، در بخش نظرات همین مقاله بپرسید؛ خودم جواب می‌دهم.

جمع‌بندی

پایتون 3.15 نسخه‌ای است که هم برای برنامه‌نویس روزمره چیزهای ملموسی دارد (UTF-8 پیش‌فرض، پیام‌های خطای بهتر، frozendict و Comprehension های تمیزتر) و هم برای کسانی که برنامه‌های بزرگ و کتابخانه می‌نویسند (ایمپورت تنبل، sentinel، پروفایلر Tachyon و JIT سریع‌تر). اگر بخواهم فقط یک چیز را همین امروز امتحان کنید، lazy import روی یک ابزار خط فرمان قدیمی‌تان است؛ تفاوت زمان اجرا را خودتان حس می‌کنید.


آرما

علیرضا مؤید احمدی هستم و اغلب منو به اسم آرما می‌شناسن. در حال حاضر مدیر شرکت جنگل هستم و بیشتر زمانم رو اونجا صرف می‌کنم. خوشحال می‌شم از اینکه خاطرات و تجربیاتم رو با دوستانم به اشتراک بذارم.

0 دیدگاه

دیدگاهتان را بنویسید

جای‌بان آواتار

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *