Декораторы
Что такое декораторы
@kakayato_shnyaga
- это декоратор.
Декоратор - это структурный паттерн проектирования, который позволяет динамически добавлять объектам новую функциональность, оборачивая их в полезные «обёртки». Подробнее можно посмотреть в книге по паттернам которая лежит в папке book.
В питоне есть особая синтаксическая конструкция позволяющая реализовывать этот паттерн. Выглядит она так:
@dekorator
def puk():
print('puk')
Если вызвать данную функцию то результат может оказаться не таким как ты этого ожидаешь на первый взгляд. Так как декоратор может управлять твоей функцией/методом как ему вздумается.
Чтобы создать декоратор можно тупо написать функцию подобного вида:
def dekorator(func):
def wrapper():
print("before")
func()
print("after")
return wrapper
Для чего это все? Чтобы писать меньше кода. Можно например дебажить в реальном времени какую-то конкретную функцию с помощью декоратора который логирует результат функции.
Вот так например:
def log_func_result(func):
def wrapper(*args):
result = func(*args)
print("Результат функции:", result)
return result
return wrapper
@log_func_result
def calculate(x, y):
return x * y
value = calculate(3, 7)
Декораторы которые встречаются в реальном коде
Python содержит несколько встроенных декораторов. Из всех этих декораторов, самыми популярными являются эти:
@classmethod
@staticmethod
@property
Также существуют декораторы в различных разделах стандартной библиотеки Python. Одним из примеров является functools.wraps.
@classmethod
может быть вызван при помощи экземпляра класса, или напрямую, через собственный класс Python в качестве первого аргумента. В соответствии с документацией Python: он может быть вызван как в классе (например, C.f()), или в экземпляре (например, C().f()). Экземпляр игнорируется, за исключением его класса. Если метод класса вызван для выведенного класса, то объект выведенного класса передается в качестве подразумеваемого первого аргумента. Используется в основном для кастомных конструкторов, например, cls вместо явного “базового класс” позволит наследнику порождать именно наследника а не родителя.
@staticmethod
— это просто функция внутри класса. Можно вызвать как с инициализацией класса так и без создания объекта. Обычно это применяется в тех случаях, когда у вас есть функция, которая, по вашему убеждению, имеет связь с классом но при этом слабо связанна с конкретным объектом. Является аналогом static методов в Java/C++.
@property
позволит превратить метод класса в атрибут класса
Полезно когда хочется сделать какое нибудь поле которое как то зависит от других полей.
Property
class Person(object):
""""""
def __init__(self, first_name, last_name):
"""Конструктор"""
self.first_name = first_name
self.last_name = last_name
@property
def full_name(self):
"""
Возвращаем полное имя
"""
return "%s %s" % (self.first_name, self.last_name)
В данном коде мы создали класс Person в котором есть имя и фамиля как поля класса и проперти полное имя.
person = Person("Mike", "Driscoll")
print(person.first_name) # Mike
print(person.full_name) # Mike Driscoll
person.full_name = "Jackalope"
# Подобное запрещено поэтому появится ошибка:
# Traceback (most recent call last):
# File "<string>", line 1, in <fragment>
# AttributeError: can't set attribute
person.first_name = "Dan"
print(person.full_name) # Dan Driscoll