Я просто хочу сказать, что полностью согласен с тем, что проверка типов - это зло. Но питон также невероятно гибок, и я настроен быть злым. Этот код вступит в силу во время выполнения, а не во время компиляции. Вы можете сделать что-то подобное для возвращаемого типа. Нечто подобное может быть полезно для отладки, и, поскольку это декоратор, его достаточно легко удалить.
Чтобы он был полезен для отладки, вам необходимо иметь ситуацию, когда два типа имеют одинаковые атрибуты, к которым обращались, но с разной семантикой. Так что это довольно ограниченный случай. Кроме этого, вы все равно получите опечатку при запуске этого кода. Хорошей новостью является то, что это почти никогда не проблема . Я действительно не знаю, почему люди со статически типизированными языками делают из этого такое большое дело.
def types(*args, **kwargs):
arg_types = args
kwarg_types = kwargs
def decorator(f):
def func(*args, **kwargs):
for arg, arg_type in zip(args, arg_types):
if not isinstance(arg, arg_type):
raise TypeError("Wrong type suckah")
for kw, arg in kwargs.items():
if not isinstance(arg, kwarg_types[kw]):
raise TypeError("this is a bad error message")
return f(*args, **kwargs)
return func
return decorator
@types(int, str, bool, flag=bool)
def demo(i, strng, flag=False):
print i, strng, flag
demo(1, "foo", True)
try:
demo("foo", "bar", flag="foobar")
except TypeError:
print "busted on posargs"
try:
demo(1, "foo", flag=2)
except TypeError:
print "busted on keyargs"
try:
demo(1, "foo", 3)
except TypeError:
print "no use sneaking it through"