Ленивые вычисления



бет4/4
Дата21.12.2023
өлшемі29.73 Kb.
#487228
1   2   3   4
ЛЕНИВЫЕ ВЫЧИСЛЕНИЯ. Функторы

class Validation:
def __init__(self, lower, upper):
self._lower = lower
self._upper = upper


def __call__(self, arg):
def wrapper(a):
res = arg(a)
if not self._lower < res < self._upper:
raise ValueError(
'Validation failed'
)
return f'{datetime.now()}: {res}'
return wrapper

@Validation(0, 10)


def square(a):
return a**2
print(square(2))
# 2022-10-29 09:41:59.377104: 4
print(square(4))
# ValueError: Validation failed
Теперь можно передавать границы интервала напрямую в декоратор.
Классами-декораторами можно декорировать как функции, так и другие классы. Они часто встречаются в модулях, и легко отличаются от обычных тем, что их названия записаны в стиле CamelCase.

Второй пример. Создадим декоратор для вычисления значения производной функции в определенной точке x с использованием класса.


class Derivate:


def __init__(self, func):
self.__fn = func
def __call__(self, x, dx=0.0001, *args, **kwargs):
return (self.__fn(x + dx) - self.__fn(x)) / dx
Здесь в инициализаторе сохраняем ссылку на функцию, которую декорируем, а в методе __call__ принимаем один обязательный параметр x – точку, где вычисляется производная и dx – шаг изменения при вычислении производной.

Далее, определим функцию, например, синус:


def df_sin(x):


return math.sin(x)
и вызове ее пока без декорирования:

print(df_sin(math.pi/4))


После запуска программы увидим значение примерно 0.7071.
Добавим декоратор. Это можно сделать двумя способами. Первый, прописать все в явном виде:

df_sin = Derivate(df_sin)


Теперь df_sin – это экземпляр класса Derivate, а не исходная функция. Поэтому, когда она будет вызываться, то запустится метод __call__ и вычислится значение производной в точке math.pi/4.

Второй способ – это воспользоваться оператором @ перед объявлением функции:


@Derivate


def df_sin(x):
return math.sin(x)
Получим абсолютно тот же самый результат. Вот принцип создания декораторов функций на основе классов: запоминаем ссылку на функцию, а затем, расширяем ее функционал в методе __call__.


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

Достарыңызбен бөлісу:
1   2   3   4




©dereksiz.org 2024
әкімшілігінің қараңыз

    Басты бет