# Классы как зависимости { #classes-as-dependencies }

Прежде чем углубиться в систему **Внедрения Зависимостей**, давайте обновим предыдущий пример.

## `dict` из предыдущего примера { #a-dict-from-the-previous-example }

В предыдущем примере мы возвращали `dict` из нашей зависимости:

{* ../../docs_src/dependencies/tutorial001_an_py310.py hl[9] *}

Но затем мы получаем `dict` в параметре `commons` *функции-обработчика пути*.

И мы знаем, что редакторы кода не могут обеспечить достаточную поддержку (например, автозавершение) для `dict`, поскольку они не могут знать их ключи и типы значений.

Мы можем сделать лучше...

## Что делает зависимость { #what-makes-a-dependency }

До сих пор вы видели зависимости, объявленные как функции.

Но это не единственный способ объявления зависимостей (хотя он, вероятно, более распространенный).

Ключевым фактором является то, что зависимость должна быть «вызываемой».

В Python «**вызываемый**» — это всё, что Python может «вызвать», как функцию.

Так, если у вас есть объект `something` (который может и _не_ быть функцией) и вы можете «вызвать» его (выполнить) так:

```Python
something()
```

или

```Python
something(some_argument, some_keyword_argument="foo")
```

в таком случае он является «вызываемым».

## Классы как зависимости { #classes-as-dependencies_1 }

Вы можете заметить, что для создания экземпляра класса в Python используется тот же синтаксис.

Например:

```Python
class Cat:
    def __init__(self, name: str):
        self.name = name


fluffy = Cat(name="Mr Fluffy")
```

В данном случае `fluffy` является экземпляром класса `Cat`.

А чтобы создать `fluffy`, вы «вызываете» `Cat`.

Таким образом, класс в Python также является **вызываемым**.

Тогда в **FastAPI** в качестве зависимости можно использовать класс Python.

На самом деле FastAPI проверяет, что переданный объект является «вызываемым» (функция, класс или что-либо еще) и какие параметры у него определены.

Если вы передаёте «вызываемый» объект в качестве зависимости в **FastAPI**, он проанализирует параметры, необходимые для этого «вызываемого» объекта, и обработает их так же, как параметры *функции-обработчика пути*. Включая подзависимости.

Это относится и к вызываемым объектам без параметров. Работа с ними происходит точно так же, как и для *функций-обработчиков пути* без параметров.

Теперь мы можем изменить зависимость `common_parameters`, указанную выше, на класс `CommonQueryParams`:

{* ../../docs_src/dependencies/tutorial002_an_py310.py hl[11:15] *}

Обратите внимание на метод `__init__`, используемый для создания экземпляра класса:

{* ../../docs_src/dependencies/tutorial002_an_py310.py hl[12] *}

...он имеет те же параметры, что и ранее используемая функция `common_parameters`:

{* ../../docs_src/dependencies/tutorial001_an_py310.py hl[8] *}

Эти параметры и будут использоваться **FastAPI** для «решения» зависимости.

В обоих случаях она будет иметь:

* Необязательный параметр запроса `q`, представляющий собой `str`.
* Параметр запроса `skip`, представляющий собой `int`, по умолчанию `0`.
* Параметр запроса `limit`, представляющий собой `int`, по умолчанию `100`.

В обоих случаях данные будут конвертированы, валидированы, задокументированы в схеме OpenAPI и т.д.

## Как это использовать { #use-it }

Теперь вы можете объявить свою зависимость, используя этот класс.

{* ../../docs_src/dependencies/tutorial002_an_py310.py hl[19] *}

**FastAPI** вызывает класс `CommonQueryParams`. При этом создается «экземпляр» этого класса, который будет передан в качестве параметра `commons` в вашу функцию.

## Аннотация типа и `Depends` { #type-annotation-vs-depends }

Обратите внимание, что в приведенном выше коде мы два раза пишем `CommonQueryParams`:

//// tab | Python 3.8+

```Python
commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)]
```

////

//// tab | Python 3.8+ non-Annotated

/// tip | Подсказка

Рекомендуется использовать версию с `Annotated`, если возможно.

///

```Python
commons: CommonQueryParams = Depends(CommonQueryParams)
```

////

Последний `CommonQueryParams`, в:

```Python
... Depends(CommonQueryParams)
```

...это то, что **FastAPI** будет использовать, чтобы узнать, что является зависимостью.

Из него FastAPI извлечёт объявленные параметры, и именно его FastAPI будет вызывать.

---

В этом случае первый `CommonQueryParams`, в:

//// tab | Python 3.8+

```Python
commons: Annotated[CommonQueryParams, ...
```

////

//// tab | Python 3.8+ non-Annotated

/// tip | Подсказка

Рекомендуется использовать версию с `Annotated`, если возможно.

///

```Python
commons: CommonQueryParams ...
```

////

...не имеет никакого специального значения для **FastAPI**. FastAPI не будет использовать его для преобразования данных, валидации и т.д. (поскольку для этого используется `Depends(CommonQueryParams)`).

На самом деле можно написать просто:

//// tab | Python 3.8+

```Python
commons: Annotated[Any, Depends(CommonQueryParams)]
```

////

//// tab | Python 3.8+ non-Annotated

/// tip | Подсказка

Рекомендуется использовать версию с `Annotated`, если возможно.

///

```Python
commons = Depends(CommonQueryParams)
```

////

...как тут:

{* ../../docs_src/dependencies/tutorial003_an_py310.py hl[19] *}

Но объявление типа приветствуется, так как в этом случае ваш редактор кода будет знать, что будет передано в качестве параметра `commons`, и тогда он сможет помочь вам с автозавершением, проверкой типов и т.д.:

<img src="/img/tutorial/dependencies/image02.png">

## Сокращение { #shortcut }

Но вы видите, что здесь мы имеем некоторое повторение кода, дважды написав `CommonQueryParams`:

//// tab | Python 3.8+

```Python
commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)]
```

////

//// tab | Python 3.8+ non-Annotated

/// tip | Подсказка

Рекомендуется использовать версию с `Annotated`, если возможно.

///

```Python
commons: CommonQueryParams = Depends(CommonQueryParams)
```

////

**FastAPI** предоставляет сокращение для таких случаев, когда зависимость — это *конкретный* класс, который **FastAPI** будет «вызывать» для создания экземпляра этого класса.

Для этих конкретных случаев вы можете сделать следующее.

Вместо того чтобы писать:

//// tab | Python 3.8+

```Python
commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)]
```

////

//// tab | Python 3.8+ non-Annotated

/// tip | Подсказка

Рекомендуется использовать версию с `Annotated`, если возможно.

///

```Python
commons: CommonQueryParams = Depends(CommonQueryParams)
```

////

...следует написать:

//// tab | Python 3.8+

```Python
commons: Annotated[CommonQueryParams, Depends()]
```

////

//// tab | Python 3.8 non-Annotated

/// tip | Подсказка

Рекомендуется использовать версию с `Annotated`, если возможно.

///

```Python
commons: CommonQueryParams = Depends()
```

////

Вы объявляете зависимость как тип параметра и используете `Depends()` без какого-либо параметра, вместо того чтобы *снова* писать полный класс внутри `Depends(CommonQueryParams)`.

Аналогичный пример будет выглядеть следующим образом:

{* ../../docs_src/dependencies/tutorial004_an_py310.py hl[19] *}

...и **FastAPI** будет знать, что делать.

/// tip | Подсказка

Если это покажется вам более запутанным, чем полезным, не обращайте внимания — это вам не *нужно*.

Это просто сокращение. Потому что **FastAPI** заботится о том, чтобы помочь вам свести к минимуму повторение кода.

///
