Python进阶: Decorator 装饰器你太美
函数 -> 装饰器
函数的4个核心概念
1.函数可以赋与变量
def func(message):
print('Got a message: {}'.format(message)) send_message = func
send_message('hello world')
#输出
#Got a message: hello world
2.函数可以当作函数的参数
def get_message(message):
return 'Got a message: ' + message def root_call(func, message):
print(func(message)) root_call(get_message, 'hello world')
输出
#Got a message: hello world
3.函数里嵌套函数
def func(message):
def get_message(message):
print('Got a message: {}'.format(message))
return get_message(message) func('hello world')
输出
#Got a message: hello world
4.函数作为函数返回值(闭包)
def func_closure():
def get_message(message):
print('Got a message: {}'.format(message))
return get_message send_message = func_closure()
send_message('hello world')
#输出
#Got a message: hello world
简单装饰器
例
def my_decorator(func):
def wrapper():
print('wrapper of decorator')
func()
return wrapper def greet():
print('hello world') greet = my_decorator(greet)
greet()
使用语法糖 @
def my_decorator(func):
def wrapper():
print('wrapper of decorator')
func()
return wrapper @my_decorator
def greet():
print('hello world') greet()
# 输出
# wrapper of decorator
# hello world
带有参数的装饰器
def my_decorator(func):
def wrapper(message):
print('wrapper of decorator')
func(message)
return wrapper @my_decorator #相当于 greet == wrapper(message)
def greet(message):
print(message) greet('hello world')
# 输出
#wrapper of decorator
#hello world
这个装饰器只能用在有一个参数的函数,如果想对任意参数的函数通用,可以这么写
def my_decorator(func):
def wrapper(*args, **kwargs):
print('wrapper of decorator')
func(*args, **kwargs)
return wrapper
带自定义参数的装饰器
def repeat(num):
def my_decorator(func):
def wrapper(*args, **kwargs):
for i in range(num):
print('wrapper of decorator')
func(*args, **kwargs)
return wrapper
return my_decorator @repeat(4)
def greet(message):
print(message) greet('hello world') # 输出:
# wrapper of decorator
# hello world
# wrapper of decorator
# hello world
# wrapper of decorator
# hello world
# wrapper of decorator
# hello world
原函数还是原函数?
greet.__name__
#输出
'wrapper' help(greet)
# 输出
Help on function wrapper in module __main__: wrapper(*args, **kwargs)
可以看出,原函数的原信息会被wrapper取代
import functools def my_decorator(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
print('wrapper of decorator')
func(*args, **kwargs)
return wrapper @my_decorator
def greet(message):
print(message) greet.__name__ # 输出
#'greet'
类装饰器
class Count:
def __init__(self, func):
self.func = func
self.num_calls = 0 def __call__(self, *args, **kwargs):
self.num_calls += 1
print('num of calls is: {}'.format(self.num_calls))
return self.func(*args, **kwargs) @Count
def example():
print("hello world") example() # 输出
# num of calls is: 1
# hello world example() # 输出
# num of calls is: 2
# hello world
装饰器的嵌套
@decorator1
@decorator2
@decorator3
def func():
...
#相当于 decorator1(decorator2(decorator3(func)))
import functools def my_decorator1(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
print('execute decorator1')
func(*args, **kwargs)
return wrapper def my_decorator2(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
print('execute decorator2')
func(*args, **kwargs)
return wrapper @my_decorator1
@my_decorator2
def greet(message):
print(message) greet('hello world') # 输出
# execute decorator1
# execute decorator2
# hello world
装饰器的实例用法
1)身份验证,不登录不允许操作
import functools def 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 @authenticate
def post_comment(request, ...)
...
2)日志记录 可测试函数的执行时间
import time
import functools def log_execution_time(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_time
def calculate_similarity(items):
...
3) 合法性检测
import functools def validation_check(input):
@functools.wraps(func)
def wrapper(*args, **kwargs):
... # 检查输入是否合法 @validation_check
def neural_network_training(param1, param2, ...):
... LRU cache. @lru_cache缓存装饰器
@lru_cache
def check(param1, param2, ...) # 检查用户设备类型,版本号等等
...
4) try...excaption
class ServerDebugHelper:
@classmethod
def debug(cls):
def decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
try:
return func(*args, **kwargs)
except:
import traceback
print(traceback.format_exc())
return wrapper
return decorator
参考
极客时间《Python核心技术与实战》专栏
Python进阶: Decorator 装饰器你太美的更多相关文章
- python进阶04 装饰器、描述器、常用内置装饰器
python进阶04 装饰器.描述器.常用内置装饰器 一.装饰器 作用:能够给现有的函数增加功能 如何给一个现有的函数增加执行计数的功能 首先用类来添加新功能 def fun(): #首先我们定义一个 ...
- Python进阶(六)----装饰器
Python进阶(六)----装饰器 一丶开放封闭原则 开放原则: 增加一些额外的新功能 封闭原则: 不改变源码.以及调用方式 二丶初识装饰器 装饰器: 也可称装饰器函数,诠释开放封闭原则 ...
- Python进阶之装饰器
函数也是对象 要理解Python装饰器,首先要明白在Python中,函数也是一种对象,因此可以把定义函数时的函数名看作是函数对象的一个引用.既然是引用,因此可以将函数赋值给一个变量,也可以把函数作为一 ...
- 项目解析1、登录验证用户是否存在 储备知识 Python 之 decorator装饰器
下面是我对 装饰器 这一小节的总结, 以及自己的理解. 注:[本文中的代码参考上述教程] 很多时候我会把Python的很多语法与C++相融合,在C++中,函数的名称即为函数的地址,我们可以通过定义成为 ...
- python进阶(三)~~~装饰器和闭包
一.闭包 满足条件: 1. 函数内嵌套一个函数: 2.外层函数的返回值是内层函数的函数名: 3.内层嵌套函数对外部作用域有一个非全局变量的引用: def func(): print("=== ...
- [Python进阶]002.装饰器(1)
装饰器(1) 介绍 HelloWorld 需求 使用函数式编程 加入装饰器 解析 介绍 Python的装饰器叫Decorator,就是对一个模块做装饰. 作用: 为已存在的对象添加额外功能. 与Jav ...
- Python进阶(装饰器)
from datetime import datetime def log(func):#func表示装饰器作用于的函数 def wrapper(*args,**kw):#wrapper返回装饰器作用 ...
- python进阶:装饰器
1.闭包 简单理解:闭包就是多层函数的嵌套,外层函数的返回值是内层函数的引用. def out_func(n): num = 100 def in_fucn(*args,**kwargs): # no ...
- Python进阶之decorator装饰器
decorator装饰器 .note-content {font-family: "Helvetica Neue",Arial,"Hiragino Sans GB&quo ...
随机推荐
- 为什么要监控sql语句,以及如何监控,都有哪几种方式可以监控。
快速阅读 为什么要监控sql语句,以及如何监控,都有哪几种方式可以监控. 我们知道sql server 中有个工具叫sql profile ,可以实时监控sql server中 执行的sql 语句,以 ...
- 给定一个二叉搜索树(BST),找到树中第 K 小的节点
问题:给定一个二叉搜索树(BST),找到树中第 K 小的节点. 出题人:阿里巴巴出题专家:文景/阿里云 CDN 资深技术专家. 考察点: 1. 基础数据结构的理解和编码能力 2. 递归使用 参考答案 ...
- 2019SDN课程阅读作业(2)
1.过去20年中可编程网络的发展可以分为几个阶段?每个阶段的贡献是什么? 分为三个阶段,第一个阶段是主动网络(从20世纪90年代中期到21世纪初),它在网络中引入了可编程功能,以实现更大的创新:第二个 ...
- embeding 是什么
要搞清楚embeding先要弄明白他和one hot encoding的区别,以及他解决了什么one hot encoding不能解决的问题,带着这两个问题去思考,在看一个简单的计算例子 以下引用 Y ...
- springboot整合vue实现上传下载文件
https://blog.csdn.net/yhhyhhyhhyhh/article/details/89888953 文章目录 springboot整合vue实现上传下载文件 1上传下载文件api文 ...
- Cannot start compilation: the output path is not specified for module "salesystem". Specify the output path in Configure Project.
错误是发生在从github上checkout自己的项目时.因为没有将配置文件一起上传,所以在运行java程序时有了这个报错: Cannot start compilation: the output ...
- 手写MyBatis ORM框架实践
一.实现手写Mybatis三个难点 1.接口既然不能被实例化?那么我们是怎么实现能够调用的? 2.参数如何和sql绑定 3.返回结果 下面是Mybatis接口 二.Demo实现 1.创建Maven工程 ...
- 初始化html font-size
(function () { var docEl = document.documentElement, resizeEvt = 'orientationchange' in window ? 'or ...
- Vue 及双向数据绑定 Vue事件 以及Vue中的ref获取dom节点
<template> <div id="app"> <h2>{{msg}}</h2> <input type="te ...
- 一个Redis实例适合存储不同应用程序的数据吗?
Redis支持多个数据库,并且每个数据库的数据是隔离的不能共享,并且基于单机才有,如果是集群就没有数据库的概念. Redis是一个字典结构的存储服务器,而实际上一个Redis实例提供了多个用来存储数据 ...