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 ...
随机推荐
- js函数运行方式一览
定义对象然后调用 j = {} j["delete"]=function () { console.log("ok") } j["delete&quo ...
- T-MAX-冲刺总结
T-MAX-冲刺总结 这个作业属于哪个课程 班级链接 这个作业要求在哪里 作业要求的链接 团队名称 T-MAX 这个作业的目标 冲刺总结 作业的正文 T-MAX-冲刺总结 其他参考文献 面向B站,百度 ...
- git只提交修改部分的代码
思路: 先用git status 查找出哪些文件被修改过了,然后 只git commit odin/code/pom.xml 1. $ git status (查看当前更改的代码) On branch ...
- python3 selenium模块Chrome设置代理ip的实现
python3 selenium模块Chrome设置代理ip的实现 selenium模块Chrome设置代理ip的实现代码: from selenium import webdriver chrome ...
- 在mac中安装tmux
在mac 中安装Tmux: 在终端输入如下命令: brew install tmux Tmux 的快捷键前缀(Prefix) 为了使自身的快捷键和其他软件的快捷键互不干扰,Tmux 提供了一个快捷键 ...
- [原][GIS]ARCGIS投影坐标系转换
ARCGIS投影坐标转换步骤: 1.在ARCGIS中加入需要转换投影坐标的数据 2.打开“工具组”中的 “数据管理工具组”(Data Management Tools) 3.打开“数据管理工具组”中的 ...
- Qt获取时间戳作为图片名
Qt获取时间戳作为图片名 //保存图片 void SaveRealsenseImg() { QString picIndexName = dataSavePath; picIndexName.appe ...
- g++编译时遇到问题undefined reference to
文件目录结构体为: src 和include 分别用来存放.cpp文件和 .hpp文件 其中:src文件夹下有需要的文件 simulator_client.cpp crc32.cpp : includ ...
- ABAP DEMO33 选择周的搜索帮助
效果图 *&---------------------------------------------------------------------**& Report YCX_02 ...
- [转]C++ STL中的Binary search(二分查找)
链接地址:https://www.cnblogs.com/wkfvawl/p/9475939.html