#!/usr/bin/python # encoding:utf-8 from inspect import signature from functools import wraps def typeassert(*ty_args, **ty_kwargs): def decorate(func): # If in optimized mode, disable type checking if not __debug__: return func # 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) # Enforce type assertions across supplied arguments 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 @typeassert(int, z=int) def spam(x, y, z=42): return x, y, z print(spam(1, 2, 3)) print(spam(1, 2, "4"))
输出:
(1, 2, 3)
Traceback (most recent call last):
File "D:/workerspace/python3_learning/test/atest10.py", line 39, in <module>
print(spam(1, 2, "4"))
File "D:/workerspace/python3_learning/test/atest10.py", line 24, in wrapper
'Argument {} must be {}'.format(name, bound_types[name])
TypeError: Argument z must be <class 'int'>