Advanced Python Vocabulary: Async, Type Hints, and Modern Python Features (англійською)

Вивчайте англійську лексику, яку використовують старші розробники Python під час перегляду коду і обговорення архітектури — async/ await, співпрограми, протоколи, TypedDict, дескриптори, метакласи і компроміси GIL.

Старші ролі Python вимагають вільності у лексиці, з якою початківці рідко стикаються: співпрограми, дескриптори, структурне підтипування, метакласи. У перегляді коду, обговоренні архітектури і технічних інтерв’ ю використання цих термінів точно сигналізує про те, що ви глибоко розумієте Python — не лише синтаксично, але й семантично. Цей посібник присвячений розриву у словниковому запасі між « пише Python щодня » і « думає в Python. »

Асинхронний Python

async/await — синтаксис Python для написання асинхронного коду. Функція, визначена async def є короткочасною функцією; виклик її повертає короткочасний об’єкт. Короткий опис:

Цикл подій event loop є планувальником, який керує виконанням співпрограм — він запускає співпрограми, обробляє зворотні виклики вводу/ виводу і відправляє завдання. Стандартна бібліотека надає ** asyncio **; ** uvloop ** є швидшим замінником, побудованим на libuv. Інженери кажуть: * “Переключити сервер на uvloop - це дає нам приблизно 2x пропускну здатність на I / O-обмежені завантаження.” *

генератор є функцією, яка використовує yield для лінивого виробництва значень. Асинхронний генератор використовує async def і yield разом, виробляючи значення асинхронно. Вони різні: генератори є синхронними; асинхронні генератори споживають async for.

async context manager реалізує __aenter__ і __aexit__ і використовується з async with. “База даних підключення пулу виставляє асинхронний контекст менеджер — завжди використовуйте його, ніколи не викликайте acquire/release вручну.”

Введіть системний словник

Система підказок типів Python значно зросла. Ключові терміни, які використовують старші розробники:

Protocol (від typing ) визначає структурне підтипування — клас задовольняє протокол, якщо він має необхідні методи та атрибути, незалежно від спадкування. Це іноді називається «качучим введенням з анотаціями типів». “Використовуйте Protocol тут замість ABC — ми не хочемо змушувати викликаючих успадковувати з нашого класу.”

** TypedDict ** визначає словник з певними, введеними ключами. Він використовується там, де клас даних буде надмірно інженерований або де JSON-подібні структури потребують безпеки типів.

** Literal ** обмежує значення певним набором констант: Literal["GET", "POST", "PUT"]. ** TypeVar ** визначає загальну змінну типу. ** ParamSpec ** захоплює специфікацію параметра виклику — використовується для написання декораторів, які зберігають підпис обгорнутої функції.

Інженери в оглядах коду пишуть: “Анотація повернення типу тут повинна бути TypeVar пов’язана з Sequence — ви втрачаєте інформацію про тип, анотуючи як list.”

Об’єктний тип і класи даних

** dataclass ** (з dataclasses ) автоматично створює __init__, __repr__ і __eq__ з анотацій класів. Екосистема має дві популярні альтернативи: attrs (потужніша, попередня класам даних) і Pydantic (додає перевірку під час виконання — кожне поле перевіряється при створенні екземпляра, а не тільки статично перевіряється на тип).

descriptor це об’єкт, який надає доступ до атрибутів за допомогою реалізації __get__, __set__, або __delete__. Властивості є найвідомішим дескриптором. Інженери, які розуміють дескриптори, можуть роздумувати про те, як ORM, Pydantic і класи даних працюють під капотом.

** метакласом ** є клас, екземпляри якого є класами. Метакласи перехоплюють створення класів і можуть змінювати атрибути класів, реєструвати підкласів або накладати обмеження. Вони потужні і складні; поширене питання в інтерв’ю: “Коли ви використовуєте метакласи замість декоратора класів?”

Модель паралельності

** GIL (Global Interpreter Lock) ** — це мутек у CPython, який запобігає одночасному виконанню байт- коду Python декількома потоками. Це означає, що багатопоточна в Python не забезпечує паралельності для роботи, обмеженої процесором — тільки один потік запускає Python в один момент часу.

Компромиси:

  • ** asyncio ** — найкраще для завантажень, пов’ язаних з вводом/ виведенням; однопоточна, без додаткових витрат на GIL, з високою одночасністю завдяки спільній багатозадачній роботі
  • ** потокове** — корисне для роботи з вхідно- вихідними даними, яка використовує блокувальні бібліотеки, несумісні з asyncio; обмежено GIL для роботи з процесором
  • ** багатопроцесорність ** — обходить GIL за допомогою окремих процесів; найкраще для паралельності, пов’ язаної з процесором, але має більші витрати на IPC

Інженери чітко це формулюють: “Не використовуйте потоки для цього — GIL буде серіалізувати процесорні перетворення. Використовуйте багатопроцесорність з пулом, або відправляйте роботу до служби працівника.”

Приклади реальних коментарів PR

    • « Цю процедуру викликають без очікування — вона ніколи не буде виконана. » *
  • “Замінити цю анотацію dict на TypedDict — нам потрібні ключі, які можна статично перевіряти.”
  • “Декоратор втрачає підпис обгорнутої функції — використовуйте functools.wraps і додайте ParamSpec, щоб зберегти його.”
    • “Цей метакласний об’ єкт робить занадто багато — розгляньте, чи не досягне декоратор класів тієї ж мети з меншою кількістю магії.” *

Наступні кроки

Виберіть з цієї статті одну з концепцій, що вас найбільше цікавить, і напишіть фрагмент Python з 10 рядків, який демонструє цю концепцію — з рядком доку англійською мовою, у якому буде пояснено, що саме вона робить і чому. Потім прочитайте код CPython для відповідного модуля (asyncio, dataclasses, typing) протягом 20 хвилин. Читання коду реалізації — це найшвидший шлях до володіння досконалим словником.

Розвиток комунікації: розробка комунікаційних технологій

Концепції async програмування, типові підказки ( typing ), і сучасні можливості Python - як Protocols і TypedDicts - представляють собою значний зсув в тому, як ми думаємо про дизайн коду і підтримку. Але для людей, для яких англійська мова не є рідною, усвідомлення нюансів комунікації навколо цих технологій може бути особливо складним. Це не просто про знання технічних визначень; це про розуміння тонких фраз, що використовуються під час перегляду коду, архітектурних дискусій і навіть простих розмов Slack. Давайте посмотрим, как это будет выглядеть на практике.

Одним з поширених сценаріїв є коментар перегляду коду. Уявіть, що ви отримуєте: « Ця програма могла б отримати користь від більш явного типу повернення ». Спочатку це може здатися звинуваченням або просто заплутаним жаргоном. Однак, основне значення полягає в тому, що розробник хоче переконатися, що функція async завжди повертає щось — певне значення, або, можливо, навіть виняток — для ясності і передбачуваності. Ця фраза заохочує вас задуматися про обробку помилок і можливі несподівані наслідки. Аналогічно, коли хтось описує протокол як «надання структури і забезпечення безпеки типів», це допомагає перенести фокус від простого розуміння синтаксису до розпізнавання його призначення: ретельний дизайн і запобігання помилкам на ранньому етапі. Використання фраз на кшталт «притримується» або «реалізує» при обговоренні протоколів є критичним. Це про передачу намірів — що ви будуєте компонент, який гарно вписується в більшу, добре визначену систему.

Інша часто зустрічається ситуація виникає під час описів Pull Request (PR). Розробник може написати: «Ця рефакторизація вводить TypedDict для поліпшення перевірки даних і зменшення потенційних помилок під час виконання». Це не тільки технічна зміна; це про те, щоб сформулювати * чому * ця зміна була зроблена - для покращення надійності і запобігання помилок. Пояснення переваг використання підказок типів у цьому контексті підкреслює їх роль у статичному аналізі, що дозволяє таким інструментам, як MyPy, ловити проблеми, перш ніж вони стануть проблемами виробництва. Мова підкреслює проактивне запобігання помилкам, а не реактивне зневадження. Це про продаж цінності добре типованої системи.

Крім того, дискусії навколо Global Interpreter Lock (GIL) і його компромісів часто включають складне фразування. Сказати «GIL обмежує справжню паралельність в задачах, пов’язаних з процесором» набагато ефективніше, ніж просто сказати «GIL існує». Перше повідомляє про вплив - що навіть з декількома ядрами, однопоточна природа Python обмежує прибутки продуктивності для деяких операцій. Зрозуміти такі терміни як «обхідні шляхи» і «асинхронний вхід/вихід» стає важливим при обговоренні стратегій для зменшення цих обмежень.

import asyncio

async def my_coroutine():
    await asyncio.sleep(1)
    print("Coroutine finished")

asyncio.run(my_coroutine())

Цей простий приклад демонструє основну концепцію функції async і як вона взаємодіє з петлею подій. Це реальна ілюстрація, яку можна використовувати для пояснення фундаментальних принципів асинхронного програмування, що дозволяє більш цілеспрямованим обговоренням його застосування в рамках проекту.

Поширені запитання

Про що ця стаття "Advanced Python Vocabulary: Async, Type Hints, and Modern Python Features (англійською)"?

Вивчайте англійську лексику, яку використовують старші розробники Python під час перегляду коду і обговорення архітектури — async/ await, співпрограми, протоколи, TypedDict, дескриптори, метакласи і компроміси GIL.

Чи безкоштовна ця стаття?

Так. Усі статті на CoderSlingo, включно з цією, доступні безкоштовно без реєстрації.

Скільки часу займає читання "Advanced Python Vocabulary: Async, Type Hints, and Modern Python Features (англійською)"?

Приблизно 9 min.