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. Для выхода из данной ситуации я пока придумал два метода решения:

  1. Можно передавать все аргументы, как kwargs, что не очень удобно.
  2. Унаследовать класс от какого-то "класса-затычки", и передавать в первый аргумент тип класса родителя, что также не самый удобный вариант по многим причинам, к тому же, работать для класс методов второй способ не будет.

Так вот, сам вопрос, можно ли как-то изменить возвращаемый объект класса inspect, чтобы удалить первый элемент(self или cls). Немного изучив данную библиотеку я не нашёл никого способа это сделать, хотя я не отрицаю, что мог его пропустить.


Ответы (0 шт):