# functools.cached\_property()

### &#x20;@functools.cached\_property(*func*)

Преобразует метод класса в свойство, значение которого вычисляется один раз, а затем кэшируется как обычный атрибут на время существования экземпляра. Аналогично [property ()](https://docs.python.org/3/library/functions.html#property) (декоратор **@property**) с добавлением кеширования. Полезно для дорогостоящих вычисляемых свойств экземпляров, которые в противном случае фактически неизменяемы.

Пример:

```python
class DataSet:

    def __init__(self, sequence_of_numbers):
        self._data = tuple(sequence_of_numbers)

    @cached_property
    def stdev(self):
        return statistics.stdev(self._data)
```

Механизм **cached\_property ()** несколько отличается от [property ()](https://docs.python.org/3/library/functions.html#property). Обычный атрибут блоков свойств записывает, если не определен установщик. Напротив, ***cached\_property*** разрешает запись.

Декоратор ***cached\_property*** запускается только при поиске и только тогда, когда атрибут с таким же именем не существует. Когда он запускается, ***cached\_property*** записывает в атрибут с тем же именем. Последующее чтение и запись атрибута имеет приоритет над методом ***cached\_property*** и работает как обычный атрибут.

Кешированное значение можно очистить, удалив атрибут. Это позволяет снова запустить метод ***cached\_property***.

Обратите внимание, что этот декоратор мешает работе словарей совместного использования ключей [PEP 412](https://www.python.org/dev/peps/pep-0412/). Это означает, что словари экземпляров могут занимать больше места, чем обычно.

Кроме того, этот декоратор требует, чтобы атрибут `__dict__` в каждом экземпляре был изменяемым отображением. Это означает, что он не будет работать с некоторыми типами, такими как метаклассы (поскольку атрибуты `__dict__` в экземплярах типов являются прокси только для чтения для пространства имен классов), и те, которые указывают `__slots__` без включения `__dict__` в качестве одного из определенных слотов (как такие классы вообще не предоставляют атрибут `__dict__`).

Если изменяемое сопоставление недоступно или если требуется совместное использование ключей с эффективным использованием пространства, эффект, аналогичный **cached\_property ()**, может быть достигнут с помощью стекирования [property()](https://docs.python.org/3/library/functions.html#property) поверх [cache ()](https://treasuremaster.gitbook.io/python-docs/moduli-standartnoi-biblioteki-1/funkcionalnye-programmnye-moduli/functools/functools.cache):

```python
class DataSet:
    def __init__(self, sequence_of_numbers):
        self._data = sequence_of_numbers

    @property
    @cache
    def stdev(self):
        return statistics.stdev(self._data)
```

*Новое в версии 3.8*.
