8.3【装饰器】定义带参数的装饰器

实现一个装饰器,用来检查被装饰函数的参数类型。装饰器可以通过参数指明函数参数的类型,调用时如果检测出类型不匹配则抛出异常
@typeassert(str,int,int)
def f(a,b,c):
	...
@typeassert(y=list)
def g(x,y):
	...
#
提取函数签名:inspect.signature()
带参数的装饰器,也就是根据参数定制化一个装饰器。可以看成生产装饰器的工厂。每次调用typeassert,返回一个特定的装饰器,然后用它去修饰其他函数

def typeassert(*ty_args, **ty_kargs): # 类型断言;参数灵活
	def decorator(func): # 真正装饰器函数,接收一个函数参数
		def wrapper(*args, **kargs): # 根据typeassert参数定制化一个装饰器,实现wrapper函数
			return func(*args, **kargs)
		return wrapper
	return decorator
# 实现类型检查功能
def typeassert(*ty_args, **ty_kargs): 
	def decorator(func): 
		# 获取函数参数和类型的映射关系;func -> a,b
		# d = {'a':int,'b':str} ; 通过参数得知
		def wrapper(*args, **kargs): 
			# arg in d, instance(arg, d[arg])
			return func(*args, **kargs)
		return wrapper
	return decorator

# 在py3中,获取函数签名信息
from inspect import signature
def f(a,b,c=1): pass
sig = signature(f)
sig.parameter
a = sig.parameter['a']
a.name # a
a.kind # 位置参数或者是关键字参数
a.default # 默认值
c = sig.parameters['c']
c.deault # 1

bargs = sig.bind(str,int,int) # 数量与参数必保持一致
bargs.arguments['a'] # builtins.str
sig.bind_partial(str) # 只对某些参数做类型要求

#
from inspect import signature
def typeassert(*ty_args, **ty_kargs): 
	def decorator(func):
		sig = signature(func)
		btypes = sig.bind_partial(*ty_args, **ty_kargs).arguments
		def wrapper(*args, **kargs): 
			for name, obj in sig.bind(*args, **kargs).arguments.items():
				if name in btypes:
					if not isinstance(obj, btypes[name]):
						raise TypeError('"%s" must be "%s"' % (name,btypes[name]))
			return func(*args, **kargs)
		return wrapper
	return decorator
@typeassert(int, str, list)
def f(a,b,c):
	print(a,b,c)

f(1,'abc',[1,2,3])
f(1,2,[1,2,3]) # 报错,b必须为str


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值