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 ...
随机推荐
- NoSql数据库MongoDB系列(1)——MongoDB简介
一.NoSQL简介 NoSQL(Not Only SQL ),意即“不仅仅是SQL” ,指的是非关系型的数据库 .是一项全新的数据库革命性运动,早期就有人提出,发展至2009年趋势越发高涨.No ...
- package.json 字段说明
以vue的package.json为例: { // 名称 "name": "vue", // 版本 "version": "2.6 ...
- ThinkPHP5使用phpspreadsheet导入导出Excel
引用类: use PhpOffice\PhpSpreadsheet\IOFactory; use PhpOffice\PhpSpreadsheet\Cell\Coordinate; use Php ...
- SQL Server 查找空值
需要查找某一列为空的数据 )NULL不能用 “=”运算符 )NULL不支持+-*/ <> )不同的函数对NULL的支持不一样,使用前要测试,不能靠猜,不能凭经验
- Windows 下使用OpenSSL生成RSA公钥和私钥
Windows 下使用OpenSSL生成RSA公钥和私钥 (1)下载OpenSSL 可到该地址下载OpenSSL: https://www.openssl.org/source/(https://ww ...
- DBGrid中插入DateTimePicker
DateTimePicker inside a DBGrid Here's how to place a TDateTimePicker into a DBGrid. Create visually ...
- git切换到某个tag, 从tag切换回当前分支
git clone 整个仓库后使用,以下命令就可以取得该 tag 对应的代码了 git checkout tag_name 但是,这时候 git 可能会提示你当前处于一个“detached HEAD& ...
- k8s中正确删除一个pod
1.先删除pod 2.再删除对应的deployment 否则只是删除pod是不管用的,还会看到pod,因为deployment.yaml文件中定义了副本数量 实例如下: 删除pod [root@tes ...
- 【linux学习笔记三】链接命令
链接命令:ln link =============华丽的分割线============= ln又有软链接和硬链接 //硬链接特征(不建议创建硬链接) 1.拥有相同的i节点和存储block块,可以看做 ...
- Find minimum number of people to reach to spread a message across all people in twitter
Considering that I'ld would like to spread a promotion message across all people in twitter. Assumin ...