Python 高手编程系列一千零一十八:用法和有用的例子

由于装饰器在模块被首次读取时由解释器来加载,所以它们的使用应受限于通用的包装器(wrapper)。如果装饰器与方法的类或所增强的函数签名绑定,那么应该将其重构为
常规的可调用对象,以避免复杂性。在任何情况下,装饰器在处理 API 时,一个好的做法
是将它们聚集在一个易于维护的模块中。
常见的装饰器模式如下所示。
• 参数检查。
• 缓存。
• 代理。
• 上下文提供者。

参数检查
检查函数接受或返回的参数,在特定上下文中执行时可能有用。举个例子,如果一个
函数要通过 XML-RPC 来调用,那么 Python 无法像静态语言那样直接提供其完整签名。当
XML-RPC 客户端请求函数签名时,就需要用这个功能来提供内省能力。
自定义装饰器可以提供这种类型的签名,并确保输入和输出代表自定义的签名参数:
rpc_info = {}
def xmlrpc(in_=(), out=(type(None),)):
def _xmlrpc(function):

注册签名

func_name = function.name
rpc_info[func_name] = (in_, out)
def _check_types(elements, types):
“”“用来检查类型的子函数。”“”
if len(elements) != len(types):
raise TypeError(‘argument count is wrong’)
typed = enumerate(zip(elements, types))
for index, couple in typed:
arg, of_the_right_type = couple
if isinstance(arg, of_the_right_type):
continue
raise TypeError(
‘arg #%d should be %s’ % (index,
of_the_right_type))

包装过的函数

def __xmlrpc(*args): # 没有允许的关键词

检查输入的内容

checkable_args = args[1:] # 去掉 self
check_types(checkable_args, in)

运行函数

res = function(*args)

检查输出的内容

if not type(res) in (tuple, list):
checkable_res = (res,)
else:
checkable_res = res
_check_types(checkable_res, out)

函数及其类型检查成功

return res
return __xmlrpc
return _xmlrpc
装饰器将函数注册到全局字典中,并将其参数和返回值保存在一个类型列表中。注意,
这个示例做了很大的简化,为的是展示装饰器的参数检查功能。
使用示例如下:
class RPCView:
@xmlrpc((int, int)) # two int -> None
def meth1(self, int1, int2):
print(‘received %d and %d’ % (int1, int2))
@xmlrpc((str,), (int,)) # string -> int
def meth2(self, phrase):
print(‘received %s’ % phrase)
return 12
在实际读取时,这个类定义会填充rpc_infos 字典,并用于检查参数类型的特定环境中:

rpc_ _info
{‘meth2’: ((<class ‘str’>,), (<class ‘int’>,)), ‘meth1’: ((<class
‘int’>, <class ‘int’>), (<class ‘NoneType’>,))}
my = RPCView()
my.meth1(1, 2)
received 1 and 2
my.meth2(2)
Traceback (most recent call last):
File “”, line 1, in
File “”, line 26, in __xmlrpc
File “”, line 20, in _ check _types
TypeError: arg #0 should be <class ‘str’>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值