همین امروز فرداست که پایتون ۳.۱۲، آخرین ورژن پایتون release بشه (اطلاعات کامل زمانبندی این ریلیس رو اینجا بخونید) بیاید ببینیم این ورژن نسبت به ورژن ۳.۱۱ که پارسال همین موقعها ریلیس شد داشته :-)
پایتون ۳.۱۲ آخرین نسخهی پایدار منتشر شده است. در این نسخه ما ترکیبی از تغییراتی در خود زبان و در stdlib داریم. تغییرات stdlib تمرکز بیشتری روی پاک کردن موارد deprecate شده، صحیحتر کار کردن و کارایی دارن. ماژول distutils
از stdlib حذف شده و پشتیبانی از filesystem در ماژولهای pathlib و os خیلی پیشرفت کردن، به علاوه چندین ماژول هم بهبودهای خیلی خوب در performance داشتن.
در تغییراتی که در خود زبان مشاهده میکنیم، کارایی زبان بالاتر رفته، بسیاری از محدودیتهای f stringها حذف شده و پیشنهادات ...Did you mean خیلی بیشتر و بهتر شدند. یک syntax جدید برای معرفی generic types و type aliases معرفی شده.
این مقاله قرار نیست توضیحات دقیق و کاملی در مورد همهی تغییرات بده، برای بررسی خیلی دقیق و ریز و همچنین علت تغییرات میتونید به PEPهای این تغییرات و Library Reference و همچنین Language Reference مراجعه کنید.
سینتکسی که در PEP 484 برای Generic Classes و Generic Functions معرفی شد، یه کمی خیلی verbost و البته زشت ?? بود اما با PEP 695 بعد ۹ سال یک سینتکس جدید و بسیار زیبا براشون زبان معرفی شده.
قبل از این پپ Generic Classes اینجوری معرفی میشدن:
که خداییش خیلی زشتن ??
اما الان چنین سینتکس زیبایی رو داریم:
برای توابع هم قبلا از این سینتکس زشتا استفاده میشد:
اما الان:
بسیار خلاصه، زیبا و البته شبیه به زبانهایی که سالهای سال جنریک و سینتکس خوبی براش داشتن به این جدول نگاه کنید:
و خوب اگه دقت کنیم میبینیم که کمی از اسکالا و گو و سوئیفت اسکی رفتیم ?
به علاوهی این سینتکس جدید، یه سینتکس جدید دیگه هم برای تعریف TypeAliasها معرفی شده. قبلنا برای تعریف یک TypeAlias چنین کدی مینوشتیم:
اما حالا:
برای این PEP تحقیق و بحث بسیاری شده و Specification و Implementation عه بلند و بالایی داره:
خیلی زیاده نه؟ مال Generatorها رو دیدید ?؟
برای توضیحات بیشتر و عمق ماجرا یه سر به PEP 695 بزنید.
در این ورژن f stringها بالاخره پدر مادردار شدن و محدودیتهای گذشتهشون رو پشتسر گذاشتن و از نو در زبان تعریف شدن.
ویژگی f stringها ابتدا در PEP 498 توسط آقای Eric V. Smith در سال ۲۰۱۵ و پایتون ۳.۶ معرفی شدند و سینتکس خیلی زیبایی رو برای Literal String Interpolation به زبان اضافه کردن، اما بعد از ۸ سال core devها اومدن گرامری که برای توصیف اونها نوشته شده بود رو بهتر کردن که راحتی و انعطافپذیری اونها رو برای ما end userها و library developerها بیشتر کردن و از اون طرف هم زحمت نگهداری کدهایی که برای پارس کردن f stringها بود رو خیلی کم کردن. بیاید تا کمی از محدودیتهای f stringها رو ببینیم:
که بجاش باید این کار رو میکردیم:
اما الان:
یا مثلا برای f stringهای تو در تو:
اما الان:
اما الان:
اما الان:
اما با تلاشهای بسیاری که برای نسل جدید f stringها شده ما:
با تغییراتی که روی نحوهی lex کردن f stringها انجام دادن، الان دیگه مستقیما میتونن با PEG Parserعی که از ورژن ۳.۹ جایگزین (1)LL پارسر قدیمی پایتون شده، اونها رو parse کنن؛ که اگه گفتید خوبیش چیه؟ حالا میتونن برای گزارش اشتباهاتی که توی f stringها نوشتیم گزارش خیلی دقیقتری بدن، تا قبل از پایتون ۳.۱۲:
اما الان:
برای مطالعهی بیشتر میتونید یه سری به PEP 701 بزنید.
یکی از فیچرهایی که زبان پایتون از نسخهی ۱.۵ (سال ۱۹۹۷) داشته این بوده که توی یک process میتونستیم چند تا مفسر رو ران کنیم، ولی خب مضراتش خیلی بیشتر از مزیتهاش بوده، اما بعد از ۲۶ سال یه nerd اومده و خیلی خوب اون رو برای پایتون نوشته: A Per-Interpreter GIL برای کامل متوجه شدن این ویژگی PEP 684 رو بخونید. اما به طور خلاصه:
پپ شمارهی ۶۸۴ کانسپتی روی در سطح C API عه پایتون معرفی کرده که میتونیم در یک process چندین مفسر که هر کدوم GIL خودشون رو دارن ران کنیم، که باعث میشه که بتونیم از یک CPU عه multi-core نهایت استفاده رو ببریم. اگه میخواید از این فیچر در سطح پایتون استفاده کنید باید تا ورژن ۳.۱۳ پایتون صبر کنید ?
اگه بخوایم توی یک جمله از آقای دکتر Mark Shannon راجع به چیزی که نوشتن بشنویم:
C++ and Java developers expect to be able to run a program at full speed (or very close to it) under a debugger. Python developers should expect that too.
در واقع وقتی کد پایتون رو با یک profiler و یا یک debugger ران میکنیم به طور معمول سرعت کد ما با یک
مرتبهی خییلی عظیمی (order of magnitude) کاهش پیدا میکنه! اما اقای مارک شنون کدطلا اومدن یک
API برای به اصطلاح خودشون low impact monitoring واسه پایتون نوشتن که از این ریلیس به بعد از
sys.monitoring قابل دسترسی خواهند بود. میزان low impact بودن چیزی هم که ارائه میدن:
اطلاعات کامل این فیچر هم میتونید از PEP 669 دریافت کنید.
برای اینکه خیلی خوب این ویژگی رو درک کنیم، باید اول یکمی مقدمه بچینیم و یه سری چیز رو با هم تست کنیم و خوبیاش رو بشمریم و سپس بگیم ایول حالا توی سطح پایتون هم اینو داریم.
تایپ سیستم پایتون برای کار کردن ماها با binary data دو تا تایپ built-in برامون داره: bytes and bytearrays.
تعریف خود داکیومنتیشن پایتون برای Bytes:
که خیلی خلاصه شما میتونید دقیقا مثل یک str بهش نگاه کنید که فقط باینری عه! دیدید توی زبان سی ما میایم از تایپ عه char استفاده میکنیم، بعد مثلا برای حرف A عدد ۶۵ جاش ذخیره میشه؟ این هم دقیقا همینه:
اما این تایپ bytes یک آبجکت immutable هست و mutable counterpartشون تایپ bytearray هست:
توضیح کامل چرایی وجود این تایپها و چه قابلیتهایی دارن، توی این مقاله اصلا نمیگنجه! اگه وقت کردم ایشالا یه مقاله جدا برای بایتها مینویستم
برگردیم سر اینکه چرا اصلا داریم اینا توضیح میدیم؛ استفاده از این تایپها خصوصا هنگام ذخیرهسازی و کار کردن با دیتاهایی که ما مثلا باز میکنیم (یه عکس یا یه فایل موسیقی مثلا) استفاده میشن، چون بالاخره این فایلهای موسیقی عکس یه سری بایت هستن که به حالت خاصی انکود شدن، توی پایتون هم ما بهشون به صورت باینری دسترسی داریم.
حالا میرسیم به اصل ماجرا
وقتی داریم با این فایلها کار میکنیم، خصوصا وقتی که به قسمتهایی ازشون نیاز داریم راهحل ساده اینه که اونا رو (چون sequence type هستن و sequence typeها از sliceها پشتیبانی میکنن) اسلایس اسلایس کنیم. برای مثال بیاید یه bytes خییییلی گنده درست کنیم:
یک میلیارد x کنار هم ??
۹۵۳ فاکینگ مگابایت مموری اشغال کرده! بنظرتون اگه این آبجکت رو اسلایس اسلایس کنیم، چی میشه؟ بیاید تا دو قسمتش کنیم و ذخیرهش کنیم:
که منطقیه! چرا؟ چون وقتی آبجکتی رو اسلایس میکنیم، پایتون یک کپی از روی اون میسازه! اما خب دردسازه ?? همین الان همین کنسول حدودا دو گیگ مموری گرفته!! دو تا 953 مگابایت! و این هر چقدر که شما بیشتر اسلایس انجام بدید، ادامه پیدا میکنه! که برای سایزها کوچیک خیلی مسئلهی مهمی نیست ولی برای چیزای حجیم چرا!
آیا پایتون براش راهحل نداره؟ البته که داره ? پایتون راهحلی ارائه داده که شما به طور کاملا مستقیم به buffer (در واقع لایهای از مکانی که اون آبجکتتوی مموری ذخیره شده) دسترسی داشته باشید و بدون کپی کردنهای بیخودی، از اونجا چیزی بخونید یا بنویسید،
یه امای بزرگ اینجا هست، اون آبجکت باید از Buffer Protocol پشتبانی کنه، طبق تعریف بسیار دقیق و زیبایی داک پایتون، بافر پروتوکل اینه:
یه مثال یگه بزنم تا متوجه بشید این کپی کردنها کجا ممکنه دردسرساز بشن، فرضضضض کنید یه فایل باینری خیلی بلندی داریم (دقیقا مثل مثالمون یک میلیارد x پشت سر هم) و میخوایم تیکههای منتخب و زیادی ازش رو توی یه فایل دیگه بنویسیم، یه مثال خیلی کوچیک:
اینکه بیایم هی تیکه تیکه اسلایسش کنیم و اون تیکه اسلاید رو بدیم به تابع write مموریمون پر پر پر میشه و پراسس kill میشه؛ اما حالا که داریم از باینری تایپها استفاده میکنیم و از قضا اینا از بافر پروتوکل پشتیبانی میکنن میتونیم اونها بدون کپی شدن اسلایس کنیم ? اینجاست با یک تایپ جدید به اسم memoryview آشنا میشیم:
توضیح کامل این تایپ هم مثل تایپهای قبلی هم توی این مقاله نمیگنجه اما تبعات استفاده ازش چرا ?
بیاید تا با استفاده از memoryview اون آبجکت خیلی گندهمون رو اسلایس کنیم ببینیم چی میشه؛ ابتدا یک memoryview ازش میسازیم:
چه سایزی ? صفر!
حالا بیاید تا اسلایس کنیم:
و باز هم سایز صفر، این دقیقا به این دلیله که ما با first_half دقیقا به اون تکه از مموری دستری داریم که اون آبجکت توش هست و هیچ کپیای انجام ندادیم. و میتونیم براحتی ازش هر جایی که بخوایم استفاده کنیم و باز هم اسلایسش کنیم و هیچ memory overhead عی توی برنامهمون نداشته باشیم.
اما چیزی که در پایتون ۳.۱۲ بوسیلهی PEP 688 اضافه شده، اینه که همین buffer protocol رو به سطح پایتون آورده و شما میتونید custom buffer classes بنویسید و ازشون نهایت استفاده رو ببرید:
طبق این PEP دو تا داندر متد جدید به پایتون اضافه شده: __buffer__
و __release_buffer__
که داندر بافر باید یک memoryview برگردونه و داندر ریلیس بافر اون رو ریلیس کنه!
برای توضیحات کاملتر PEP 688 رو بخونید.
کامپریهنشنها یکی از جذابترین سینتکسهای معرفی شده (و البته اسکی رفته از notationهای ریاضی) هستن که طرفداران زیادی هم دارن! طوری که کامپریهنشنها تا قبل از پایتون ۳.۱۲ کار میکردن این بود که هر کامپریهنشن تبدیل به یک تابع میشد و اون تابع دقیقا مثل یک تابع معمولی ساخته، کامپایل و صدا زده میشد:
ببینید، اولین بایتکدی که اجرا میشه (هنگام صدا زده شدن تابع) اینه که یک کد آبجکت لود بشه!! کد آبجکت کدی که داخل اون listcomp نوشته شده! بعدش ببینید! دو تا بایتکد توی ۴ و ۱۰! MAKE_FUNCTION و CALL_FUNCTION و این یعنی پایتون از اون بایتکد یک تابع میسازه و سپس صداش میزنه! و این یعنی عینا مثل توابع باهاشون رفتار میشه، یعنی یک frame object براشون تشکیل میشه، توی tracebackها نشون داده میشن و بعد از استفاده شدن اون تابع درست شده، دور انداخته میشه! و این یعنی هر بار تابع f رو صدا بزنید، یک تابع دیگه درونش ساخته میشه!
اما خب این روند دیگه توی پایتون ۳.۱۲ وجود نداره و comprehensionها به اصطلاح inline میشن و دیگه تابعی براشون درست نمیشه! و فریمی هم نخواهند داشت:
و در استکتریس هم نیستن:
برای اطلاعات کاملتر و جزئیات بیشتر PEP 709 رو بخونید.
حالا ما میتونیم type annotation دقیقتری برای آنبپک کردن kwargs** داشته باشیم:
(سباستین رامیرز نویسندهی FastAPI: ???)
برای کسب اطلاعات بیشتر به PEP 692 مراجعه کنید.
یه دکوریتور بیخودی هم نوشتن که نه تنها کد رو زشت میکنه بلکه که میخوام به کسایی که این PEP رو قبول کردن تا اومد پایتون ۳.۱۳ یعنی تقریبا یک سال روزی ۱۰۰ مرتبه فحش بدم!!!
کلا به من چه هم که این زبونا این رو دارن:
ولی بهرحال آورده شده، و این جونور زشت اینجوریه:
و البته یکی از دلایلی هم که براش آوردن اینه که اگه یه متدی از یک کلاسی رو شما override کرده باشید و بعد توی کلاس Parent اسمش رو عوض کنید، کدتون ران میشه، و فقط وقتی به هنگام استفاده از متدی که توی کلاس فرزند هست میرسه اون متد با اسم قبلی (که قبلا اون متد رو اورراید کرده بود) رو اجرا میکنه که ممکنه تولید باگ کنه. فرض کنید چنین کدی داریم:
حالا اسم foo داخل کلاس Parent رو عوض میکنیم، چیزی که داریم:
اما پپ میگه اگه با override دکوریتاش کرده بوده باشیم type checker بهش گیر خواهد داد.
ولی بهرحال کلی کد زشت به پایتون اضافه کردن ?? میتونید راجع بهش در PEP 698 بخونید.
[(b := 1) for a, b.prop in some_iter]
re.sub()
and re.subn()
and corresponding re.Pattern
methods) ۲ تا ۳ برابر سریعتر شدند.طبق این صفحه:
حدود ۱۵۳۲ تا issue برای این ریلیس بسته شدند که اولین اونها (از نظر زمان ایجاد شدن):
هست که تاریخ باز شدنش سال ۲۰۰۳ هست و آخرین اونها:
که ۵ روز پیش باز شده و یک روز بعد بسته شده :))
پایتون هر سال داره خیلی پیشرفت میکنه، ما به عنوان پایتون دولوپرها باید همیشه اخبار پایتون رو دنبال کنیم و ببینیم چه چیزهای جدید توی هر ریلیس بهش اضافه تا بتونیم کدهای بهتری رو بنویسیم.