У меня есть два простых декоратора, которые выполняют базовую проверку типов аргументов функций и типов возвращаемых значений. Они работают по отдельности, но не в комбинации. И да, я знаю о статической проверке типов в Python 3.6, но я все еще хочу, чтобы это работало :)
Я адаптировал код Python 2 из примера здесь: https://www.python.org/dev/peps/pep-0318/#examples
from functools import wraps
def accepts(*types):
def check_accepts(f):
assert len(types) == f.__code__.co_argcount
@wraps(f)
def new_f(*args, **kwds):
for (a, t) in zip(args, types):
assert isinstance(a, t), \
"arg %r does not match %s" % (a,t)
return f(*args, **kwds)
return new_f
return check_accepts
def returns(rtype):
def check_returns(f):
@wraps(f)
def new_f(*args, **kwds):
result = f(*args, **kwds)
assert isinstance(result, rtype), \
"return value %r does not match %s" % (result,rtype)
return result
return new_f
return check_returns
@accepts(int, (int,float))
@returns((int,float))
def func(arg1, arg2):
return arg1 * arg2
Я получаю ошибку утверждения на assert len(types) == f.__code__.co_argcount
.
Второстепенный вопрос, если позволите, заключается в том, как я могу расширить декоратор @accepts
для работы с методами класса, которые могут иметь аргументы self
или cls
.
Измените украшения, как показано ниже:
@returns((int,float))
@accepts(int, (int,float))
def func(arg1, arg2):
return arg1 * arg2
Точно нет. Декораторы в питоне — это варианты (?) или реализация шаблона декоратора в разработке программного обеспечения. Порядок, в котором они представлены, имеет большое значение. Больше информации об этом docs.python.org/3/reference/compound_stmts.html#функция, и я впервые узнал об этом сам, здесь: stackoverflow.com/questions/739654/…. Добавьте в закладки, как я. :)
Хотя это немного по-хакерски, не так ли?