#python
Вопрос:
Я хочу использовать декоратор для проверки типа ввода. Декоратор-это:
def inputAssert(*ty_args, **ty_kwargs):
def decorate(func):
print('input assert')
# Map function argument names to supplied types
sig = 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(
'Argument {} must be {}'.format(name, bound_types[name])
)
return func(*args, **kwargs)
return wrapper
return decorate
И это отлично подходит для работы. Но, если я использую его в классе, произойдет что-то странное.
Мой код таков:
from functools import wraps
from inspect import signature
def inputAssert(*ty_args, **ty_kwargs):
def decorate(func):
print('input assert')
# Map function argument names to supplied types
sig = 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(
'Argument {} must be {}'.format(name, bound_types[name])
)
return func(*args, **kwargs)
return wrapper
return decorate
class Demo:
@inputAssert(name=str)
def __init__(self, name=''):
print('base model init')
if __name__ == '__main__':
print('------ base model init start----')
d = Demo(name='xx')
print('------ base model init finish----')
Я кое-что печатаю inputAssert
. На мой взгляд, печатная информация должна быть:
------ base model init start----
input assert
base model init
------ base model init finish----
Однако на самом деле информация является:
input assert
------ base model init start----
base model init
------ base model init finish----
Это приводит меня в замешательство. Почему inputAssert
это не требуется Demo(name='xx')
?
Комментарии:
1. Ваше
print()
утверждение находится в самой функции декоратора, поэтому оно выполняется, как толькоDemo
__init__
определен метод класса. Вы хотели бы поместить его в функцию обертки.2. декоратор
inputAssert
выполняется, когда он загружает код с классом — перед запускомif __name__ == '__main__':
— поэтому он печатает его перед запускомbase model init start
3. Большое вам спасибо~~~ @Iguananaut, @furas