Вступ до типів Python¶
🌐 Переклад ШІ та людьми
Цей переклад виконано ШІ під керівництвом людей. 🤝
Можливі помилки через неправильне розуміння початкового змісту або неприродні формулювання тощо. 🤖
Ви можете покращити цей переклад, допомігши нам краще спрямовувати AI LLM.
Python підтримує додаткові «підказки типів» (також звані «анотаціями типів»).
Ці «підказки типів» або анотації — це спеціальний синтаксис, що дозволяє оголошувати тип змінної.
За допомогою оголошення типів для ваших змінних редактори та інструменти можуть надати вам кращу підтримку.
Це лише швидкий навчальний посібник / нагадування про підказки типів у Python. Він покриває лише мінімум, необхідний щоб використовувати їх з FastAPI... що насправді дуже мало.
FastAPI повністю базується на цих підказках типів, вони дають йому багато переваг і користі.
Але навіть якщо ви ніколи не використаєте FastAPI, вам буде корисно дізнатись трохи про них.
Примітка
Якщо ви експерт у Python і ви вже знаєте все про підказки типів, перейдіть до наступного розділу.
Мотивація¶
Давайте почнемо з простого прикладу:
def get_full_name(first_name, last_name):
full_name = first_name.title() + " " + last_name.title()
return full_name
print(get_full_name("john", "doe"))
🤓 Other versions and variants
def get_full_name(first_name, last_name):
full_name = first_name.title() + " " + last_name.title()
return full_name
print(get_full_name("john", "doe"))
Виклик цієї програми виводить:
John Doe
Функція виконує наступне:
- Бере
first_nameтаlast_name. - Перетворює першу літеру кожного з них у верхній регістр за допомогою
title(). - Конкатенує їх разом із пробілом по середині.
def get_full_name(first_name, last_name):
full_name = first_name.title() + " " + last_name.title()
return full_name
print(get_full_name("john", "doe"))
🤓 Other versions and variants
def get_full_name(first_name, last_name):
full_name = first_name.title() + " " + last_name.title()
return full_name
print(get_full_name("john", "doe"))
Редагуйте це¶
Це дуже проста програма.
Але тепер уявіть, що ви писали це з нуля.
У певний момент ви розпочали б визначення функції, у вас були б готові параметри...
Але тоді вам потрібно викликати «той метод, який перетворює першу літеру у верхній регістр».
Це буде upper? Чи uppercase? first_uppercase? capitalize?
Тоді ви спробуєте давнього друга програміста — автозаповнення редактора коду.
Ви надрукуєте перший параметр функції, first_name, тоді крапку (.), а тоді натиснете Ctrl+Space, щоб запустити автозаповнення.
Але, на жаль, ви не отримаєте нічого корисного:

Додайте типи¶
Давайте змінимо один рядок з попередньої версії.
Ми змінимо саме цей фрагмент, параметри функції, з:
first_name, last_name
на:
first_name: str, last_name: str
Ось і все.
Це «підказки типів»:
def get_full_name(first_name: str, last_name: str):
full_name = first_name.title() + " " + last_name.title()
return full_name
print(get_full_name("john", "doe"))
🤓 Other versions and variants
def get_full_name(first_name: str, last_name: str):
full_name = first_name.title() + " " + last_name.title()
return full_name
print(get_full_name("john", "doe"))
Це не те саме, що оголошення значень за замовчуванням, як це було б з:
first_name="john", last_name="doe"
Це зовсім інше.
Ми використовуємо двокрапку (:), не знак дорівнює (=).
І додавання підказок типів зазвичай не змінює того, що відбувається, порівняно з тим, що відбувалося б без них.
Але тепер уявіть, що ви знову посеред процесу створення функції, але з підказками типів.
У той самий момент ви спробуєте викликати автозаповнення за допомогою Ctrl+Space і побачите:

Разом з цим ви можете прокручувати, переглядаючи опції, допоки не знайдете ту, що «щось вам підказує»:

Більше мотивації¶
Перевірте цю функцію, вона вже має підказки типів:
def get_name_with_age(name: str, age: int):
name_with_age = name + " is this old: " + age
return name_with_age
🤓 Other versions and variants
def get_name_with_age(name: str, age: int):
name_with_age = name + " is this old: " + age
return name_with_age
Оскільки редактор знає типи змінних, ви не тільки отримаєте автозаповнення, ви також отримаєте перевірку помилок:

Тепер ви знаєте, щоб виправити це, вам потрібно перетворити age у строку за допомогою str(age):
def get_name_with_age(name: str, age: int):
name_with_age = name + " is this old: " + str(age)
return name_with_age
🤓 Other versions and variants
def get_name_with_age(name: str, age: int):
name_with_age = name + " is this old: " + str(age)
return name_with_age
Оголошення типів¶
Щойно ви побачили основне місце для оголошення підказок типів. Як параметри функції.
Це також основне місце, де ви б їх використовували у FastAPI.
Прості типи¶
Ви можете оголошувати усі стандартні типи у Python, не тільки str.
Ви можете використовувати, наприклад:
intfloatboolbytes
def get_items(item_a: str, item_b: int, item_c: float, item_d: bool, item_e: bytes):
return item_a, item_b, item_c, item_d, item_e
🤓 Other versions and variants
def get_items(item_a: str, item_b: int, item_c: float, item_d: bool, item_e: bytes):
return item_a, item_b, item_c, item_d, item_e
Модуль typing¶
Для деяких додаткових випадків використання може знадобитися імпортувати елементи зі стандартної бібліотеки, модуля typing. Наприклад, коли ви хочете оголосити, що щось має «будь-який тип», ви можете використати Any з typing:
from typing import Any
def some_function(data: Any):
print(data)
Generic типи¶
Деякі типи можуть приймати «параметри типів» у квадратних дужках, щоб визначити їх внутрішні типи. Наприклад, «list строк» буде оголошений як list[str].
Ці типи, які можуть приймати параметри типів, називаються generic типами або generics.
Ви можете використовувати ті самі вбудовані типи як generics (з квадратними дужками та типами всередині):
listtuplesetdict
List¶
Наприклад, давайте визначимо змінну, яка буде list із str.
Оголосіть змінну з тим самим синтаксисом двокрапки (:).
Як тип вкажіть list.
Оскільки список є типом, який містить деякі внутрішні типи, ви поміщаєте їх у квадратні дужки:
def process_items(items: list[str]):
for item in items:
print(item)
🤓 Other versions and variants
def process_items(items: list[str]):
for item in items:
print(item)
Інформація
Ці внутрішні типи в квадратних дужках називаються «параметрами типу».
У цьому випадку str — це параметр типу, переданий у list.
Це означає: «змінна items — це list, і кожен з елементів у цьому списку — str».
Зробивши це, ваш редактор може надати підтримку навіть під час обробки елементів зі списку:

Без типів цього майже неможливо досягти.
Зверніть увагу, що змінна item є одним із елементів у списку items.
І все ж редактор знає, що це str, і надає підтримку для цього.
Tuple and Set¶
Ви повинні зробити те ж саме, щоб оголосити tuple і set:
def process_items(items_t: tuple[int, int, str], items_s: set[bytes]):
return items_t, items_s
🤓 Other versions and variants
def process_items(items_t: tuple[int, int, str], items_s: set[bytes]):
return items_t, items_s
Це означає:
- Змінна
items_t— цеtupleз 3 елементами:int, щеint, таstr. - Змінна
items_s— цеset, і кожен його елемент має типbytes.
Dict¶
Щоб оголосити dict, вам потрібно передати 2 параметри типу, розділені комами.
Перший параметр типу для ключів у dict.
Другий параметр типу для значень у dict:
def process_items(prices: dict[str, float]):
for item_name, item_price in prices.items():
print(item_name)
print(item_price)
🤓 Other versions and variants
def process_items(prices: dict[str, float]):
for item_name, item_price in prices.items():
print(item_name)
print(item_price)
Це означає:
- Змінна
prices— цеdict:- Ключі цього
dictмають типstr(скажімо, назва кожного предмета). - Значення цього
dictмають типfloat(скажімо, ціна кожного предмета).
- Ключі цього
Union¶
Ви можете оголосити, що змінна може бути будь-яким із кількох типів, наприклад int або str.
Щоб визначити це, використовуйте вертикальну риску (|), щоб розділити обидва типи.
Це називається «union», тому що змінна може бути чимось із об’єднання цих двох множин типів.
def process_item(item: int | str):
print(item)
Це означає, що item може бути int або str.
Можливо None¶
Ви можете оголосити, що значення може мати тип, наприклад str, але також може бути None.
def say_hi(name: str | None = None):
if name is not None:
print(f"Hey {name}!")
else:
print("Hello World")
Використання str | None замість просто str дозволить редактору допомогти вам виявити помилки, коли ви могли б вважати, що значенням завжди є str, хоча насправді воно також може бути None.
Класи як типи¶
Ви також можете оголосити клас як тип змінної.
Скажімо, у вас є клас Person з імʼям:
class Person:
def __init__(self, name: str):
self.name = name
def get_person_name(one_person: Person):
return one_person.name
🤓 Other versions and variants
class Person:
def __init__(self, name: str):
self.name = name
def get_person_name(one_person: Person):
return one_person.name
Потім ви можете оголосити змінну типу Person:
class Person:
def __init__(self, name: str):
self.name = name
def get_person_name(one_person: Person):
return one_person.name
🤓 Other versions and variants
class Person:
def __init__(self, name: str):
self.name = name
def get_person_name(one_person: Person):
return one_person.name
І знову ж таки, ви отримуєте всю підтримку редактора:

Зверніть увагу, що це означає: «one_person — це екземпляр класу Person».
Це не означає: «one_person — це клас з назвою Person».
Pydantic моделі¶
Pydantic — це бібліотека Python для валідації даних.
Ви оголошуєте «форму» даних як класи з атрибутами.
І кожен атрибут має тип.
Потім ви створюєте екземпляр цього класу з деякими значеннями, і він перевірить ці значення, перетворить їх у відповідний тип (якщо є потреба) і надасть вам об’єкт з усіма даними.
І ви отримуєте всю підтримку редактора з цим отриманим об’єктом.
Приклад з офіційної документації Pydantic:
from datetime import datetime
from pydantic import BaseModel
class User(BaseModel):
id: int
name: str = "John Doe"
signup_ts: datetime | None = None
friends: list[int] = []
external_data = {
"id": "123",
"signup_ts": "2017-06-01 12:22",
"friends": [1, "2", b"3"],
}
user = User(**external_data)
print(user)
# > User id=123 name='John Doe' signup_ts=datetime.datetime(2017, 6, 1, 12, 22) friends=[1, 2, 3]
print(user.id)
# > 123
Інформація
Щоб дізнатись більше про Pydantic, перегляньте його документацію.
FastAPI повністю базується на Pydantic.
Ви побачите набагато більше цього всього на практиці в Навчальний посібник - Посібник користувача.
Підказки типів з анотаціями метаданих¶
У Python також є можливість додавати додаткові метадані до цих підказок типів за допомогою Annotated.
Ви можете імпортувати Annotated з typing.
from typing import Annotated
def say_hello(name: Annotated[str, "this is just metadata"]) -> str:
return f"Hello {name}"
🤓 Other versions and variants
from typing import Annotated
def say_hello(name: Annotated[str, "this is just metadata"]) -> str:
return f"Hello {name}"
Сам Python нічого не робить із цим Annotated. А для редакторів та інших інструментів тип усе ще є str.
Але ви можете використати це місце в Annotated, щоб надати FastAPI додаткові метадані про те, як ви хочете, щоб ваш застосунок поводився.
Важливо пам’ятати, що перший параметр типу, який ви передаєте в Annotated, — це фактичний тип. Решта — це лише метадані для інших інструментів.
Наразі вам просто потрібно знати, що Annotated існує і що це стандартний Python. 😎
Пізніше ви побачите, наскільки потужним це може бути.
Порада
Той факт, що це стандартний Python, означає, що ви й надалі отримуватимете найкращий можливий досвід розробки у вашому редакторі, з інструментами, які ви використовуєте для аналізу та рефакторингу коду тощо. ✨
А також те, що ваш код буде дуже сумісним із багатьма іншими інструментами та бібліотеками Python. 🚀
Підказки типів у FastAPI¶
FastAPI використовує ці підказки типів для виконання кількох речей.
З FastAPI ви оголошуєте параметри з підказками типів, і отримуєте:
- Підтримку редактора.
- Перевірку типів.
...і FastAPI використовує ті самі оголошення для:
- Визначення вимог: з параметрів шляху запиту, параметрів запиту, заголовків, тіл, залежностей тощо.
- Перетворення даних: із запиту в необхідний тип.
- Перевірки даних: що надходять від кожного запиту:
- Генерування автоматичних помилок, що повертаються клієнту, коли дані недійсні.
- Документування API за допомогою OpenAPI:
- який потім використовується для автоматичної інтерактивної документації користувальницьких інтерфейсів.
Все це може здатися абстрактним. Не хвилюйтеся. Ви побачите все це в дії в Навчальний посібник - Посібник користувача.
Важливо те, що за допомогою стандартних типів Python в одному місці (замість того, щоб додавати більше класів, декораторів тощо), FastAPI зробить багато роботи за вас.
Інформація
Якщо ви вже пройшли весь навчальний посібник і повернулися, щоб дізнатися більше про типи, ось хороший ресурс: «шпаргалка» від mypy.