В моем случае мне нужно, чтобы декораторы имели доступ к объекту класса, поэтому я не могу объявлять свои декораторы вне класса. Представьте себе, например, декоратор счетчика исключений класса, который будет увеличивать переменную self.Exception_count всякий раз, когда декорированный метод my_func(self) вызывает исключение. Например:
Код: Выделить всё
import functools
class Example:
def __init__(self):
self.exception_count = 0
@staticmethod
def count_exception(func):
@functools.wraps(func)
def wrapper(self, *args, **kwargs):
try:
return func(self, *args, **kwargs)
except Exception as e:
print(f"caught: {e}")
self.exception_count += 1
return wrapper
@count_exception
def foo(self):
raise RuntimeError("exception!")
x = Example()
# prints: "exception count: 0"
print(f"exception count: {x.exception_count}")
x.foo()
x.foo()
# prints: "exception count: 2"
print(f"exception count: {x.exception_count}")
Код: Выделить всё
@decorator_1
@decorator_2
# ...
@decorator_X
def foo():
pass
Я попробовал следующую реализацию, но она не работает:
Код: Выделить всё
class MyClass:
@staticmethod
def _decorator1(func):
def wrapper(self, *args, **kwargs):
print("static decorator 1")
return func(self, *args, **kwargs)
return wrapper
@staticmethod
def _decorator2(func):
def wrapper(self, *args, **kwargs):
print("static decorator 2")
return func(self, *args, **kwargs)
return wrapper
@staticmethod
def _combined_decorator(func):
@MyClass._decorator1
@MyClass._decorator2
def wrapper(self, *args, **kwargs):
return func(self, *args, **kwargs)
return wrapper
@_combined_decorator
def my_func(self):
print("my func")
x = MyClass()
x.my_func()
У меня есть несколько вариантов: использование @classmethod, изменение @MyClass._decoratorX на @_decoratorX и т. д. Но, похоже, ничего не работает.
Я использую 3.10, поэтому я думаю, что @staticmethod должен иметь возможность вызывать другой @staticmethod внутри того же класса, и это, насколько я понимаю, все, что должно потребоваться.
Есть идеи?
Подробнее здесь: https://stackoverflow.com/questions/791 ... single-one
Мобильная версия