# Встроенные декораторы

### 1. **`@staticmethod`** — статический метод

* **Что делает:** превращает метод класса в обычную функцию, которая не получает `self` или `cls` автоматически.
* **Когда применять:** метод логически относится к классу, но не зависит от состояния экземпляра или самого класса.

```python
class MathUtils:
    @staticmethod
    def add(a, b):
        return a + b

print(MathUtils.add(2, 3))  # 5
```

💡 В автотестах: удобно для хелперов, например, генераторов тестовых данных.

***

### 2. **`@classmethod`** — метод класса

* **Что делает:** передаёт в метод ссылку на сам класс (`cls`) вместо экземпляра.
* **Когда применять:** нужно работать с классом в целом (например, альтернативные конструкторы).

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

    @classmethod
    def from_fullname(cls, fullname):
        first, last = fullname.split()
        return cls(first)

user = User.from_fullname("John Smith")
print(user.name)  # John
```

💡 В автотестах: полезно для фабрик объектов Page Object.

***

### 3. **`@property`** — превращает метод в атрибут

* **Что делает:** позволяет вызывать метод как обычное свойство без скобок.
* **Когда применять:** когда нужно "ленивое" вычисление значения или валидация при установке.

```python
class Rectangle:
    def __init__(self, w, h):
        self.w = w
        self.h = h

    @property
    def area(self):
        return self.w * self.h

rect = Rectangle(3, 4)
print(rect.area)  # 12
```

💡 В автотестах: удобно, когда данные должны выглядеть как атрибуты, а не методы.

***

### 4. **`@<property>.setter`** и `@<property>.deleter`

* **Что делает:** определяет логику при изменении или удалении свойства.

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

    @property
    def name(self):
        return self._name

    @name.setter
    def name(self, value):
        if not value:
            raise ValueError("Имя не может быть пустым")
        self._name = value

u = User("John")
u.name = "Alice"
```

***

### 5. **`@functools.lru_cache`** *(технически из `functools`, но часто относят к "встроенным")*

* **Что делает:** кеширует результат функции.
* **Когда применять:** если функция часто вызывается с одними и теми же аргументами.

```python
from functools import lru_cache

@lru_cache(maxsize=None)
def slow_calc(x):
    print("Вычисление...")
    return x * x

slow_calc(2)  # вычислит
slow_calc(2)  # возьмёт из кеша
```

💡 В тестах: удобно при работе с медленными API для повторных запросов.

***

### 6. **`@dataclass`** *(из `dataclasses`)*

* **Что делает:** автоматически создаёт `__init__`, `__repr__`, `__eq__` и другие методы для класса с атрибутами.

```python
from dataclasses import dataclass

@dataclass
class User:
    name: str
    age: int

print(User("John", 30))
```

💡 В тестах: быстро описывать структуры тестовых данных.

***

### 7. **`@abstractmethod`** *(из `abc`)*

* **Что делает:** заставляет наследников обязательно реализовать метод.

```python
from abc import ABC, abstractmethod

class BaseTest(ABC):
    @abstractmethod
    def run_test(self):
        pass
```

💡 В тестах: удобно в архитектуре, где есть общий интерфейс тестов или страниц.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://kaze.gitbook.io/qa-theory/osnovy-programmirovaniya-na-python/vstroennye-dekoratory.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
