Browse Source
* Update all * Reflect latest changes in `docs/en/docs/tutorial/security/oauth2-jwt.md`pull/14911/head
committed by
GitHub
90 changed files with 549 additions and 620 deletions
@ -0,0 +1,61 @@ |
|||
# Продвинутые типы Python { #advanced-python-types } |
|||
|
|||
Ниже несколько дополнительных идей, которые могут быть полезны при работе с типами Python. |
|||
|
|||
## Использование `Union` или `Optional` { #using-union-or-optional } |
|||
|
|||
Если по какой-то причине ваш код не может использовать `|`, например, если это не аннотация типов, а что-то вроде `response_model=`, вместо вертикальной черты (`|`) можно использовать `Union` из `typing`. |
|||
|
|||
Например, вы можете объявить, что значение может быть `str` или `None`: |
|||
|
|||
```python |
|||
from typing import Union |
|||
|
|||
|
|||
def say_hi(name: Union[str, None]): |
|||
print(f"Hi {name}!") |
|||
``` |
|||
|
|||
В `typing` также есть сокращение, чтобы объявить, что значение может быть `None`, — `Optional`. |
|||
|
|||
Вот совет с моей очень субъективной точки зрения: |
|||
|
|||
- 🚨 Избегайте использования `Optional[SomeType]` |
|||
- Вместо этого ✨ используйте **`Union[SomeType, None]`** ✨. |
|||
|
|||
Оба варианта эквивалентны и под капотом это одно и то же, но я бы рекомендовал `Union` вместо `Optional`, потому что слово «optional» может наводить на мысль, что значение необязательное, тогда как на самом деле это означает «значение может быть `None`», даже если оно не является необязательным и по-прежнему требуется. |
|||
|
|||
По-моему, `Union[SomeType, None]` более явно передаёт смысл. |
|||
|
|||
Речь только о словах и названиях. Но эти слова могут влиять на то, как вы и ваша команда думаете о коде. |
|||
|
|||
В качестве примера возьмём такую функцию: |
|||
|
|||
```python |
|||
from typing import Optional |
|||
|
|||
|
|||
def say_hi(name: Optional[str]): |
|||
print(f"Hey {name}!") |
|||
``` |
|||
|
|||
Параметр `name` объявлен как `Optional[str]`, но он не является необязательным: вы не можете вызвать функцию без этого параметра: |
|||
|
|||
```Python |
|||
say_hi() # О нет, это вызывает ошибку! 😱 |
|||
``` |
|||
|
|||
Параметр `name` по-прежнему обязателен (не «optional»), так как у него нет значения по умолчанию. При этом `name` принимает `None` в качестве значения: |
|||
|
|||
```Python |
|||
say_hi(name=None) # Это работает, None допустим 🎉 |
|||
``` |
|||
|
|||
Хорошая новость: в большинстве случаев вы сможете просто использовать `|` для объявления объединений типов: |
|||
|
|||
```python |
|||
def say_hi(name: str | None): |
|||
print(f"Hey {name}!") |
|||
``` |
|||
|
|||
Так что обычно вам не о чем переживать из‑за названий вроде `Optional` и `Union`. 😎 |
|||
@ -54,7 +54,7 @@ $ pip install "fastapi[all]" |
|||
|
|||
Вы можете использовать все те же возможности валидации и инструменты, что и для Pydantic‑моделей, например разные типы данных и дополнительную валидацию через `Field()`. |
|||
|
|||
{* ../../docs_src/settings/tutorial001_py39.py hl[2,5:8,11] *} |
|||
{* ../../docs_src/settings/tutorial001_py310.py hl[2,5:8,11] *} |
|||
|
|||
/// tip | Совет |
|||
|
|||
@ -70,7 +70,7 @@ $ pip install "fastapi[all]" |
|||
|
|||
Затем вы можете использовать новый объект `settings` в вашем приложении: |
|||
|
|||
{* ../../docs_src/settings/tutorial001_py39.py hl[18:20] *} |
|||
{* ../../docs_src/settings/tutorial001_py310.py hl[18:20] *} |
|||
|
|||
### Запуск сервера { #run-the-server } |
|||
|
|||
@ -104,11 +104,11 @@ $ ADMIN_EMAIL="[email protected]" APP_NAME="ChimichangApp" fastapi run main.p |
|||
|
|||
Например, у вас может быть файл `config.py` со следующим содержимым: |
|||
|
|||
{* ../../docs_src/settings/app01_py39/config.py *} |
|||
{* ../../docs_src/settings/app01_py310/config.py *} |
|||
|
|||
А затем использовать его в файле `main.py`: |
|||
|
|||
{* ../../docs_src/settings/app01_py39/main.py hl[3,11:13] *} |
|||
{* ../../docs_src/settings/app01_py310/main.py hl[3,11:13] *} |
|||
|
|||
/// tip | Совет |
|||
|
|||
@ -126,7 +126,7 @@ $ ADMIN_EMAIL="[email protected]" APP_NAME="ChimichangApp" fastapi run main.p |
|||
|
|||
Продолжая предыдущий пример, ваш файл `config.py` может выглядеть так: |
|||
|
|||
{* ../../docs_src/settings/app02_an_py39/config.py hl[10] *} |
|||
{* ../../docs_src/settings/app02_an_py310/config.py hl[10] *} |
|||
|
|||
Обратите внимание, что теперь мы не создаем экземпляр по умолчанию `settings = Settings()`. |
|||
|
|||
@ -134,7 +134,7 @@ $ ADMIN_EMAIL="[email protected]" APP_NAME="ChimichangApp" fastapi run main.p |
|||
|
|||
Теперь мы создаем зависимость, которая возвращает новый `config.Settings()`. |
|||
|
|||
{* ../../docs_src/settings/app02_an_py39/main.py hl[6,12:13] *} |
|||
{* ../../docs_src/settings/app02_an_py310/main.py hl[6,12:13] *} |
|||
|
|||
/// tip | Совет |
|||
|
|||
@ -146,13 +146,13 @@ $ ADMIN_EMAIL="[email protected]" APP_NAME="ChimichangApp" fastapi run main.p |
|||
|
|||
Затем мы можем запросить ее в *функции-обработчике пути* как зависимость и использовать там, где нужно. |
|||
|
|||
{* ../../docs_src/settings/app02_an_py39/main.py hl[17,19:21] *} |
|||
{* ../../docs_src/settings/app02_an_py310/main.py hl[17,19:21] *} |
|||
|
|||
### Настройки и тестирование { #settings-and-testing } |
|||
|
|||
Далее будет очень просто предоставить другой объект настроек во время тестирования, создав переопределение зависимости для `get_settings`: |
|||
|
|||
{* ../../docs_src/settings/app02_an_py39/test_main.py hl[9:10,13,21] *} |
|||
{* ../../docs_src/settings/app02_an_py310/test_main.py hl[9:10,13,21] *} |
|||
|
|||
В переопределении зависимости мы задаем новое значение `admin_email` при создании нового объекта `Settings`, а затем возвращаем этот новый объект. |
|||
|
|||
@ -193,7 +193,7 @@ APP_NAME="ChimichangApp" |
|||
|
|||
Затем обновите ваш `config.py` так: |
|||
|
|||
{* ../../docs_src/settings/app03_an_py39/config.py hl[9] *} |
|||
{* ../../docs_src/settings/app03_an_py310/config.py hl[9] *} |
|||
|
|||
/// tip | Совет |
|||
|
|||
@ -226,7 +226,7 @@ def get_settings(): |
|||
|
|||
Но так как мы используем декоратор `@lru_cache` сверху, объект `Settings` будет создан только один раз — при первом вызове. ✔️ |
|||
|
|||
{* ../../docs_src/settings/app03_an_py39/main.py hl[1,11] *} |
|||
{* ../../docs_src/settings/app03_an_py310/main.py hl[1,11] *} |
|||
|
|||
Затем при любых последующих вызовах `get_settings()` в зависимостях для следующих запросов, вместо выполнения внутреннего кода `get_settings()` и создания нового объекта `Settings`, будет возвращаться тот же объект, что был возвращен при первом вызове, снова и снова. |
|||
|
|||
|
|||
@ -1,13 +1,13 @@ |
|||
# Как сделать — Рецепты { #how-to-recipes } |
|||
|
|||
Здесь вы найдете разные рецепты и руководства «как сделать» по различным темам. |
|||
Здесь вы найдете разные рецепты и руководства «как сделать» по **различным темам**. |
|||
|
|||
Большинство из этих идей более-менее независимы, и в большинстве случаев вам стоит изучать их только если они напрямую относятся к вашему проекту. |
|||
Большинство из этих идей более-менее **независимы**, и в большинстве случаев вам стоит изучать их только если они напрямую относятся к **вашему проекту**. |
|||
|
|||
Если что-то кажется интересным и полезным для вашего проекта, смело изучайте; в противном случае, вероятно, можно просто пропустить. |
|||
|
|||
/// tip | Совет |
|||
|
|||
Если вы хотите изучить FastAPI структурированно (рекомендуется), вместо этого читайте [Учебник — Руководство пользователя](../tutorial/index.md){.internal-link target=_blank} по главам. |
|||
Если вы хотите **изучить FastAPI** структурированно (рекомендуется), вместо этого читайте [Учебник — Руководство пользователя](../tutorial/index.md){.internal-link target=_blank} по главам. |
|||
|
|||
/// |
|||
|
|||
Loading…
Reference in new issue