علیرضا آیین‌مهر
علیرضا آیین‌مهر
خواندن ۶ دقیقه·۴ سال پیش

مروری بر تغییرات پایتون ۳.۹

نسخه‌ی پایدار پایتون ۳.۹، تو تاریخ ۵ اکتبر منتشر شد، تو این پست یه مرور کوتاه و کلی روی تغییرات جدیدی که روی پایتون ۳.۹ اعمال شده با هم انجام می‌دیم.


Photo by Christina Morillo from Pexels
Photo by Christina Morillo from Pexels

? امکانات سینتکسی جدید

PEP 584: Union operators added to `dict`

PEP 585: Type hinting generics in standard collections

PEP 614: Relaxed grammar restrictions on decorators

این ۳تا PEP، امکانات جدید سینتکسی رو به صورت کامل توضیح می‌دن، هر کدومش رو اینجا به صورت خلاصه مرور می‌کنیم


? PEP 584, union operators added to dict

یه Operator یا عمل‌گر جدید برای `dict` اضافه شده، کار این عمل‌گر Merge کردن ۲ یا چند `dict` هست

برای مثال:

personal_info = {'name': 'John', 'lastName': 'Doe'}
address_info = {'country': 'Doeland'}

اگر بخوایم این ۲ dict رو با هم یکی کنیم، تا قبل پایتون ۳.۹ با این روش انجام می‌دادیم

user_info = {**personal_info, **address_info}

و مقدار `user_info` می‌شد

{'name': 'John', 'lastName': 'Doe', 'country': 'Doeland'}

تو نسخه‌ی ۳.۹ با استفاده از Pipe می‌تونیم همین کار رو بکنیم

user_info = personal_info | address info

برای Assignment هم، همین Operator اضافه شده، مثال قبلی رو در نظر بگیرید، اما با این فرق که به جای `user_info` می‌خوایم، مقادیر `address_info` رو داخل `personal_info` بریزیم

personal_info |= address_info

توی این حالت، تمام keyهای address_info داخل personal_info هم Merge میشن، قبلا برای انجام این‌کار می‌تونستیم از متود `update` استفاده کنیم

personal_info.update(address_info)


? PEP 585 type hinting generics in standard collections

از پایتون ۳.۵، به پایتون Type Hinting اضافه شد.

برای مثال شما یه تابع تعریف کردید به این شکل

def round_and_sum(x, y): return round(x) + round(y)

داخل بدنه‌ی تابع، ویرایشگر یا IDE شما هیچ ایده‌ای نداره که پارامتر‌های `x` و `y` از چه نوعی هستن تا طبق Data Typeشون بهتون Auto Completion بده

برای حل این مشکل، می‌تونیم روی تعریف پارامتر‌ها بهشون Type بدیم

def round_and_sum(x: float, y: float): return round(x) + rount(y)

تو مشخص کردن نوع `x` و `y`، اگر داخل بدنه‌ی تابع، جلوشون نقطه بزاریم، بهمون متود‌های مختلف float رو پیشنهاد می‌ده، این موارد صرفا زمان Type Checking وجود دارن و تاثیری توی Runtime ندارن

توی این مثال، از float استفاده کردیم، که یک تایپ سادست، خودش چیزی رو داخل خودش نگه نمی‌داره، همین مثال رو با استفاده از Iteratorها می‌زنیم و با Generic Typeها آشنا می‌شیم

from typing import Tuple def round_and_sum(*args: Tuple[float]): result = 0 for arg in args: result += round(arg) return result

با توجه به این که `*args` یک Iterable هست از نوع Tuple، نوع خودش مشخص هست، اما نوع مقادیری که داخلش هستن مشخص نیست، باید براش از تایپ Generic که براش ارائه شده استفاده کرد، تایپ‌های Generic، یک تایپی رو به عنوان پارامتر خودشون می‌گیرن، توی مثال بالا، پارامتری که به تایپ Tuple دادم، float هست

به این شکل، اگر من داخل بدنه‌ی تابع بعدش از `args` نقطه بذارم، بهم متود‌های مربوط به `tuple` رو میده، اگر هم جلوی `args[0]` برای مثال، نقطه بذارم، بهم متود‌های `float` رو نشون میده

و اما تغییر PEP-585

تا نسخه‌ی ۳.۸ برای تایپ‌های Generic باید از کتاب‌خونه‌ی Typing استفاده می‌کردید، تو نسخه‌ی ۳.۹ برای تایپ‌های Generic هم می‌تونید از همون کلاس استفاده کنید

مثال قبلی رو تو پایتون ۳.۹ می‌نویسم

def round_and_sum(*args: tuple[float]): result = 0 for arg in args: result += round(arg) return result

همینطور که مشخصه، دیگه نیاز به Import نداره


? PEP 614, Relaxed grammar restrictions on decorators

تا قبل از پایتون ۳.۹، اگر داخل یه Class، یه Decorator تعریف می‌کردید، نمی‌تونستید هم‌زمان هم از Decorator استفاده کنید و هم از Classتون Object بسازید

یه مثال می‌زنم ساده‌تر درک کنید

class Test: def __init__(self, namespace): self.namespace = namespace def my_decorator(self, function): def wrapper(*args, **kwargs): print(f'{self.namespace} => {function.__name__} is running.') return function(*args, **kwargs) return wrapper

من اینجا یه کلاس تعریف کردم، که یه پارامتر به نام `namespace` می‌گیره، داخل کلاسم یه Decorator تعریف کردم که کارش صرفا این هست که میگه کدوم تابع با کدوم namespace اجرا شده

حالا می‌خوایم از این decorator تو کد‌های قبل نسخه‌ی ۳.۹ استفاده کنیم

@Test(namespace='Testing Environment').my_decorator def add(x, y): return x + y

خط اول، از کلاسم یه Object ساختم و "Testing Environment" رو بهش به عنوان namespace دادم، در ادامه هم متود `my_decorator` رو ازش استفاده کردم

اما در صورتی که این کد رو اجرا کنم با خطای زیر مواجه میشم

File "/tmp/py3.9.py", line 11
@Test(namespace='Testing Environment').my_decorator
^
SyntaxError: invalid syntax

تو نسخه‌های قبل ۳.۹، امکان استفاده از نقطه بعد از پرانتز به عنوان Decorator وجود نداشت، تو نسخه‌ی ۳.۹ این امکان اضافه شده

کدی که بالاتر نوشتم، روی پایتون ۳.۹ کار می‌کنه

برای این که روی نسخه‌های قبلی هم کار کنه، باید به این شکل نوشته بشه

test_env = Test(namespace='Testing Environment') @test_env.my_decorator def add(x, y): return x + y

ساخته شدن Object به صورت جدا انجام شد و از Decorator هم تونستیم استفاده کنیم



? متود‌های جدید

PEP 616: string methods to remove prefixes and suffixes.

۲تا متود خیلی خوب و جالب به `str` اضافه شده.

  1. `str.removeprefix`: حذف پیش‌وند از رشته
  2. `str.removesuffix`: حذف پس‌وند از رشته

برای مثال یه سری آدرس سایت داریم و می‌خوایم همشون رو یه شکل بکنیم، اگر با www. شروع می‌شن، این www. رو ازشون حذف کنیم و اگر با / تموم میشن، / رو هم ازشون حذف کنیم

addresses = [&quotwww.google.com&quot, &quotbing.com/&quot, &quotduckduckgo.com&quot] normalized_addresses = [] for address in addresses: normalized_address = address.removeprefix('www.') # without www. normalized_address = normalized_address.removesuffix('/') # without trailing slash normalized_addresses.append(normalized_address)

در نهایت اگر normalized_addresses رو `print` بگیریم، می‌بینیم که www. ها و / های بعد از آدرس رو حذف کرده!



? کتاب‌خانه‌ی zoneinfo به صورت Standard

به نظر من، این یکی از خوشحال‌کننده‌ترین مواردی بود انجام شد، تو نسخه‌های قبلی نیاز بود از کتاب‌خونه‌هایی مثل `pytz` استفاده کنید تا بتونید اطلاعات Timezone های دیگه رو داشته باشید

تو نسخه‌ی ۳.۹، یه کتاب‌خونه‌ی پیش‌فرض و استاندارد به نام `zoneinfo` اضافه شده که این اطلاعات رو بهتون میده و دیگه نیاز ندارید چندتا کتاب‌خونه‌ی مختلف برای اطلاعات Timezoneهای مختلف نصب کنید.

from zoneinfo import ZoneInfo from datetime import datetime, timedelta dt = datetime(2020, 10, 31, 12, tzinfo=ZoneInfo(&quotAsia/Tehran&quot)) # Output as string: 2020-10-31 12:00:00+03:30 dt.tzname() # Output: &quot+0330&quot



کلی تغییرات باحال و خفن دیگه وجود داره که اینجا پوشش نمی‌دمشون، اگر علاقه دارید، توصیه می‌کنم حتما و حتما Whats New in Python 3.9 رو داخل مستندات پایتون بررسی کنید

بهینه‌سازی‌های خیلی زیادی انجام شده، سرعت عمل‌کرد و کارایی تا حد زیادی بهبود پیدا کرده

حتا یه PEP صرفا برای برنامه‌ی انتشار پایتون نوشته و تایید شده

طبق PEP 602، هر سال، ماه October یه نسخه‌ی پایدار از پایتون منتشر میشه

برای مثال سال آینده،یک‌ماه قبل‌تر از الآن پایتون ۳.۱۰ منتشر میشه و در موردش می‌نویسم :)

PEP 602 - Python annual release cycle
PEP 602 - Python annual release cycle


پایتونبرنامه‌نویسیpython
BackEnd Developer who prefers Vue but uses React
شاید از این پست‌ها خوشتان بیاید