۲۹ شهریور ۱۴۰۳

Techboy

اخبار و اطلاعات روز تکنولوژی

با راهنمایی های نوع پایتون شروع کنید

بیاموزید که چگونه از نحو اختیاری نوع اشاره پایتون برای ایجاد کدهای تمیزتر و مفیدتر استفاده کنید.

بیاموزید که چگونه از نحو اختیاری نوع اشاره پایتون برای ایجاد کدهای تمیزتر و مفیدتر استفاده کنید.

Python بهتر است به عنوان یک زبان پویا اما قوی در نظر گرفته شود. انواع با نام چیزها مرتبط نیستند، بلکه با خود چیزها مرتبط هستند.

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

مدتی است که پایتون این توانایی را دارد که نام‌ها را با اطلاعات نوع، به هر شکلی، «حاشیه‌نویسی» کند. با Python 3.5، تایپ نکات رسماً بخشی از زبان شد (PEP 484) . با استفاده از یک ابزار یا ابزار بررسی کد، توسعه دهندگان می توانند سازگاری متغیرها و انواع آنها را در یک پایگاه کد بررسی کنند و تجزیه و تحلیل ایستا کد را انجام دهند که قبلاً دشوار یا غیرممکن بود. همه این کارها قبل از زمان، قبل از اجرای کد انجام می‌شود.

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

چگونه پایتون از تایپ راهنمایی استفاده می کند (این کار را نمی کند)

یک تصور غلط کلیدی در مورد نکات نوع پایتون نحوه استفاده از آنهاست. نکات نوع پایتون در زمان اجرا نمی استفاده می شوند، حداقل معمولاً. در واقع، زمانی که برنامه شما اجرا می شود، تمام اطلاعات نوع ارائه شده پاک شده است. نکات نوع پایتون پیش از موعد توسط سیستم بررسی نوع مورد استفاده شما استفاده می شود. به عنوان مثال، در ویرایشگر یا IDE شما. به عبارت دیگر، نکات نوع Python برای توسعه دهنده است، نه برای زمان اجرا.

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

برخی حدس زده‌اند که اشاره کردن به نوع پایتون می‌تواند به مرور زمان باعث ایجاد فورکی از زبانی شود که بصورت ایستا تایپ می‌شود، شاید به عنوان راهی برای سریع‌تر کردن پایتون. از برخی جهات این فورک قبلاً وارد شده است: Cython برای تولید کد C از پایتون از نکات نوع (اگرچه بیشتر نوع خاص خود از آنها) استفاده می کند و پروژه mypyc از Python استفاده می کند. نوع بومی اشاره به انجام همان. و پروژه‌هایی مانند Codon یا Mojo با استفاده از اعلان‌های نوع برای ایجاد یک گویش جایگزین سریع‌تر پایتون کاوش می‌کنند.

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

سینتکس نکات نوع پایتون

نکات تایپ در پایتون شامل یک دونقطه و یک اعلان نوع پس از اولین فراخوانی یک نام در فضای نام است. این یک مثال است:


name: str
age: int

name = input("Your name?")
age = int(input("Your age?"))

# alternatively, and more simply:

name: str = input("Your name?")
age: int = int(input("Your age?"))

اولین اعلان‌های name و سن با نکات نوع تضمین می‌کنند که هرگونه استفاده آتی از آن نام‌ها در آن فضای نام در مقابل آن انواع بررسی می‌شود. به عنوان مثال، این کد نامعتبر خواهد بود:


name: int
age: int

name = input("Your name?")
age = int(input("Your age?"))

از آنجایی که ما name را به عنوان یک int اعلام کرده‌ایم، و input به‌طور پیش‌فرض یک رشته را برمی‌گرداند، بررسی‌کننده نوع شکایت می‌کند. با این حال، کد همچنان اجرا می‌شود، زیرا از راهنمایی‌های نوع در زمان اجرا استفاده نمی‌شود، و خارج از انواعی که به اشتباه اشاره شده‌اند، کد عملاً کار اشتباهی انجام نمی‌دهد.

سیستم‌های بررسی نوع پایتون، در صورت امکان، سعی می‌کنند انواع را استنتاج کنند. برای مثال، فرض کنید از کد زیر بدون اعلان‌های نوع قبلی استفاده کرده‌ایم:


name = input("Your name?")
age = int(input("Your age?"))

در این صورت، بررسی‌کننده نوع می‌تواند استنباط کند که name یک رشته است (زیرا input() چیز دیگری را بر نمی‌گرداند)، و این < code>age یک int است (زیرا int() هیچ چیز دیگری را بر نمی گرداند). اما بهترین نتایج از اشاره صریح به هر متغیر حاصل می‌شود، زیرا همیشه نمی‌توان این استنتاج‌ها را انجام داد.

توابع Python hinting را تایپ کنید

توابع پایتون را می‌توان تایپ کرد، به طوری که مقادیری که می‌پذیرند و برمی‌گردانند زودتر از موعد مستند شوند. کد زیر را در نظر بگیرید:


greeting = "Hello, {}, you're {} years old"

def greet(user, age):
    return greeting.format(user, age)

name = input("Your name?")
age = int(input("How old are you?"))

print(greet(name, age))

یک ابهام در مورد این کد این است که greet() در تئوری می تواند هر نوع را برای user و age بپذیرد و می تواند هر نوع را برگرداند. . ما می‌توانیم این سردرگمی را با استفاده از راهنمایی‌های نوع:

رفع کنیم


greeting = "Hello, {}, you're {} years old"

def greet(user: str, age: int) -> str:
    return greeting.format(user, age)

name = input("Your name?")
age = int(input("How old are you?"))

print(greet(name, age))

با توجه به این راهنمایی‌های نوع برای greet()، ویرایشگر شما می‌تواند از قبل به شما بگوید که چه نوع greet() زمانی که تماسی با آن وارد می‌کنید، می‌پذیرد. کد.

باز هم، گاهی اوقات پایتون می تواند به طور خودکار استنباط کند که چه نوع هایی از یک تابع برگردانده می شوند، اما اگر قصد دارید از تایپ hinting با یک تابع استفاده کنید، بهتر است به همه چیز در مورد آن اشاره کنید – چه انواعی را در آن استفاده می کند. و همچنین انواع آن را برمی گرداند.

اشیاء کانتینر اشاره‌ای را تایپ کنید

از آنجایی که اشیایی مانند فهرست‌ها، دیکشنری‌ها و تاپل‌ها حاوی اشیاء دیگری هستند، گاهی اوقات می‌خواهیم تایپ کنیم تا نشان دهیم که چه نوع اشیایی در آنها وجود دارد. پیش از این، پایتون نیاز به استفاده از ماژول typing برای ارائه ابزارهایی برای توصیف چنین انواعی داشت، اما اکنون می‌توان آن‌ها را در نسخه‌های اخیر به صورت بومی در پایتون انجام داد.


dict_of_users: dict[int,str] = {
    ۱: "Jerome",
    ۲: "Lewis"
}

list_of_users: list[str] = [
    "Jerome", "Lewis"
]

فرهنگ لغت ها از کلیدها و مقادیری ساخته شده اند که می توانند انواع مختلفی داشته باشند. می توانید انواع یک فرهنگ لغت را با اشاره به dict[، <نوع مقدار>] توصیف کنید. و می‌توانید نوع شی را برای یک فهرست با اشاره‌ای در قالب list[] توصیف کنید.

انواع اختیاری و اتحادیه

بعضی از اشیاء یکی از چند نوع مختلف اشیاء را شامل می شوند. در این موارد، می‌توانید از Union یا اختیاری استفاده کنید. از Union برای نشان دادن اینکه یک شی می تواند یکی از چندین نوع باشد استفاده کنید. از اختیاری برای نشان دادن اینکه یک شی یا یک نوع داده شده است یا هیچ استفاده کنید. به عنوان مثال:


from typing import Dict, Optional, Union

dict_of_users: Dict[int, Union[int,str]] = {
    ۱: "Jerome",
    ۲: "Lewis",
    ۳: ۳۲
}

user_id: Optional[int]
user_id = None # valid
user_id = 3 # also vald
user_id = "Hello" # not valid!

در این مورد، ما دیکشنری داریم که ints را به عنوان کلید، اما ints یا strs را به عنوان مقادیر می‌گیرد. متغیر user_id (که می‌توانیم از آن برای مقایسه با کلیدهای فرهنگ لغت استفاده کنیم) می‌تواند یک int یا None (“بدون کاربر معتبر”) باشد. اما نه str.

در جدیدترین نسخه‌های Python، می‌توان انواع Union را با استفاده از کاراکتر pipe به شرح زیر اشاره کرد، بدون نیاز به وارد کردن:


dict_of_users: dict[int, int|str] = {
    ۱: "Jerome",
    ۲: "Lewis",
    ۳: ۳۲
         }

همچنین توجه داشته باشید که اختیاری را می توان به عنوان اتحادیه با هیچ اشاره کرد. برای مثال، int|هیچکد به جای اختیاری[int]. اگر ترجیح می‌دهید کارها را ساده نگه دارید، نیاز به وارد کردن اختیاری را کاهش می‌دهد.

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

برای ارائه راهنمایی‌های نوع کلاس‌ها، کافی است نام آنها را مانند هر نوع دیگری ارجاع دهید:


class User:
    def __init__(self, name):
        self.name = name

users: dict[int, User] = {
    ۱: User("Serdar"),
    ۲: User("Davis")
}

def inspect_user(user: User) -> None:
    print (user.name)

user1 = users[1]
inspect_user(user1)

توجه داشته باشید که inspect_user() نوع برگشتی هیچ دارد زیرا فقط خروجی را چاپ می‌کند و چیزی را بر نمی‌گرداند. (همچنین، ما معمولاً چنین چیزی را به روشی برای کلاس تبدیل می‌کنیم، اما به منظور تصویرسازی، در اینجا جداگانه توضیح داده شده است.)

هنگام استفاده از نکات نوع برای اشیاء سفارشی، گاهی اوقات نیاز داریم که برای شیئی که هنوز تعریف نشده است، یک نوع اشاره ارائه کنیم. در آن صورت، می توانید از یک رشته برای ارائه نام شی استفاده کنید:


class User:
    def __init__(self, name: str, address: "Address"):
        self.name = name
        self.address = address
        # ^ because let's say for some reason we must have
        # an address for each user

class Address:
    def __init__(self, owner: User, address_line: str):
        self.owner = owner
        self.address_line = address_line

اگر اشیایی با وابستگی متقابل دارید، مانند مثال بالا، این رویکرد مفید است. احتمالاً راه ظریف‌تری برای باز کردن آن وجود دارد، اما حداقل می‌توانید به سادگی با ارائه نام شی، راهنمایی‌های زودهنگام در همان فضای نام ارائه کنید.