> For the complete documentation index, see [llms.txt](https://kaze.gitbook.io/qa-theory/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://kaze.gitbook.io/qa-theory/osnovy-programmirovaniya-na-python/dlya-chego-nuzhno-prevrashat-metod-klassa-v-atribut.md).

# Для чего нужно превращать метод класса в атрибут

Преобразование метода класса в атрибут обычно делают для **кэширования результата** или **упрощения доступа**, когда метод не нужно вызывать каждый раз как функцию.

***

### Основные причины

#### 1. **Вычислить один раз и использовать как свойство**

* Если метод возвращает значение, которое зависит только от состояния объекта и не меняется, его можно сделать **свойством** с помощью `@property`.
* Это убирает круглые скобки при вызове и делает обращение более "атрибутным" — читается как поле.

```python
class Rectangle:
    def __init__(self, width, height):
        self.width = width
        self.height = height
    
    @property
    def area(self):
        return self.width * self.height

rect = Rectangle(10, 5)
print(rect.area)  # 50, без ()
```

Применяется в тестировании, например, для вычисления URL страницы на основе конфигурации.

***

#### 2. **Кэширование (ленивые вычисления)**

* С помощью `functools.cached_property` (Python 3.8+) метод выполняется один раз, а результат сохраняется в атрибут.
* Это полезно, когда вычисление дорогое (например, запрос в API или БД), и нет смысла повторять его каждый раз.

```python
from functools import cached_property
import time

class DataLoader:
    @cached_property
    def big_data(self):
        time.sleep(2)  # имитация долгой операции
        return [1, 2, 3]

loader = DataLoader()
print(loader.big_data)  # вычисляется 1 раз
print(loader.big_data)  # берется из кэша
```

***

#### 3. **Связывание метода с переменной**

* Иногда нужно сохранить метод в переменной для удобства передачи в другую функцию, например, как колбэк.

```python
class Math:
    def add(self, a, b):
        return a + b

m = Math()
plus = m.add  # теперь это переменная
print(plus(2, 3))  # 5
```

***

### 🔹 В автоматизации тестирования

* **`@property`** удобно использовать в Page Object Model для локаторов:

```python
class LoginPage:
    @property
    def username_field(self):
        return self.driver.find_element(By.ID, "username")
```

Теперь можно писать:

```python
login_page.username_field.send_keys("test_user")
```

вместо:

```python
login_page.username_field().send_keys("test_user")
```

* **`@cached_property`** полезно, если локатор или данные ищутся долго, но не меняются в течение теста.
