Python декоратор для проверки типов
Я читаю книгу Дэвида Близи "Python. Книга рецептов" и там приводится пример декоратора, в аргументы которого передаются типы декорируемой функции и он их проверяет в момент вызова, если тип не указан, то он считается любым. Можно использовать kwargs, если надо указать тип после пропущенного. Код прикладываю:
import inspect
from functools import wraps
def typeassert(*ty_args, **ty_kwargs):
def decorate(func):
if not __debug__:
return func
sig = inspect.signature(func)
bound_types = sig.bind_partial(*ty_args, **ty_kwargs).arguments
@wraps(func)
def wrapper(*args, **kwargs):
bound_values = sig.bind(*args, **kwargs)
for name, value in bound_values.arguments.items():
if name in bound_types:
if not isinstance(value, bound_types[name]):
raise TypeError(
f'Argument {name} must be {bound_types[name]}'
)
return func(*args, **kwargs)
return wrapper
return decorate
@typeassert(int, str, z=float)
def foo(a, b, c, z):
return f'{a}, {b}, {c}, {z}'
if __name__ == "__main__":
print(foo(1, 'bar', [], 4.0))
Всё работает отлично, за исключением одного момента, если попробовать применить данный декоратор к методам какого-либо класса, то он будет некорректно работать, поскольку считает первый параметр self или cls. Для выхода из данной ситуации я пока придумал два метода решения:
- Можно передавать все аргументы, как kwargs, что не очень удобно.
- Унаследовать класс от какого-то "класса-затычки", и передавать в первый аргумент тип класса родителя, что также не самый удобный вариант по многим причинам, к тому же, работать для класс методов второй способ не будет.
Так вот, сам вопрос, можно ли как-то изменить возвращаемый объект класса inspect, чтобы удалить первый элемент(self или cls). Немного изучив данную библиотеку я не нашёл никого способа это сделать, хотя я не отрицаю, что мог его пропустить.