[h1]python学习笔记(17)[/h1][h3]python强大的修饰器[/h3]- 修饰器的基本概念
- [/code]def func(message): print('Got a message: {}'.format(message)) send_message = func send_message('hello world')
- [code]
复制代码 def get_message(message): return 'Got a message: ' + messagedef root_call(func, message): print(func(message)) root_call(get_message, 'hello world')- [/code]def func(message): def get_message(message): print('Got a message: {}'.format(message)) return get_message(message)func('hello world')
- [code]
复制代码 def func_closure(): def get_message(message): print('Got a message: {}'.format(message)) return get_messagesend_message = func_closure()send_message('hello world')- [/code]def my_decorator(func): def wrapper(): print('wrapper of decorator') func() return wrapperdef greet(): print('hello world')greet = my_decorator(greet)greet()
- [code]
复制代码 def my_decorator(func):def wrapper(): print('wrapper of decorator') func()return wrapper@my_decoratordef greet(): print('hello world')greet()- [/code]def my_decorator(func):def wrapper(*args, **kwargs): print('wrapper of decorator') func(*args, **kwargs)return wrapper
- [code]
复制代码 import functoolsdef my_decorator(func): @functools.wraps(func) def wrapper(*args, **kwargs): print('wrapper of decorator') func(*args, **kwargs) return wrapper @my_decoratordef greet(message): print(message)greet.__name__- [/code]class Count:def __init__(self, func): self.func = func self.num_calls = 0def __call__(self, *args, **kwargs): self.num_calls += 1 print('num of calls is: {}'.format(self.num_calls)) return self.func(*args, **kwargs)@Countdef example(): print("hello world")example()# 输出num of calls is: 1hello worldexample()# 输出num of calls is: 2hello world
- 以上代码可以看到装饰器的强大,虽然用函数也能实现装饰器的作用,但是如果用装饰器的话,就会让代码看起来清晰许多,很多时候需要用到装饰器的技巧。
- [list][*]类装饰器
- [*]带参数的装饰器
- [*]在上面的描述中,我们可以用更简单的写法来标识,用@关键字来作为修饰器的关键字,@后面接着函数名.
- [/list][list][*]装饰器的基本定义如下,函数也作为对象返回,同时执行函数,我们把装饰器看做以下即可对装饰器有更加深刻的认识,greet函数指向wrapper函数,且调用了函数自身,类似于函数指针:
- [*]闭包,函数对象作为返回值
- [/list][list][*]在函数内部定义函数嵌套,调用函数
- [*]将函数作为参数,在函数中调用,基本调用示例如下:
- [/list][list][*]函数的基本概念,常见的函数调用如下所示,我们可以将函数赋给某个变量,由某个变量进行调用:
- [/list][*]python的装饰器的作用
- [code]
复制代码 import functoolsdef authenticate(func): @functools.wraps(func) def wrapper(*args, **kwargs): request = args[0] if check_user_logged_in(request): # 如果用户处于登录状态 return func(*args, **kwargs) # 执行函数 post_comment() else: raise Exception('Authentication failed') return wrapper @authenticatedef post_comment(request, ...) ...
在上述代码中对请求request尽心验证,验证时需对身份进行校验,通过统一的装饰器验证函数,提供给其他登录或者通信模块应用。- [/code]import timeimport functoolsdef log_execution_time(func): @functools.wraps(func) def wrapper(*args, **kwargs): start = time.perf_counter() res = func(*args, **kwargs) end = time.perf_counter() print('{} took {} ms'.format(func.__name__, (end - start) * 1000)) return res return wrapper @log_execution_timedef calculate_similarity(items):
- 其中我们可以到通过装饰器log_execution_time来记录每个函数的运行时间.
- [code]
复制代码 import functoolsdef validation_check(input): @functools.wraps(func) def wrapper(*args, **kwargs): ... # 检查输入是否合法 @validation_checkdef neural_network_training(param1, param2, ...): ...
- 输入合理性检查 我们在实际的程序运行过程中都会对每个参数进行校验,检查参数的合理性和合法性。
- 日志记录 我们在实际的系统运行时可能需要记录必须的函数调用记录,
- 身份认证。比如在做客户端或者服务器端进行身份认证时,需要对当前的用户传递过来的消息进行身份认证,那么每次只需要对消息中特定的信息进行验证即可得到结果。比如以下代码:
- 思考题
所谓的装饰器,其实就是通过装饰器函数,来修改函数本身的一些功能,使得函数更具有扩展型,而原函数不需要进行修改即可。可以随意扩展函数的功能。
|
|