Python装饰器的定义和使用详情
作者:程序员班长 发布时间:2021-01-26 23:22:15
标签:Python,装饰器,定义,使用
1.装饰器的定义
装饰器:给已有函数增加额外的功能的函数,本质上是一个闭包函数
特点:
1.不修改已有函数的源代码
2.不修改已有函数的调用方式
3.给已有函数增加额外的功能
4.代码执行时先解析装饰器
import time
# 装饰器原理
# def show():
# n=0
# for i in range(10000000):
# n+=i
# print('show_',n)
#
# # 定义一个闭包
# def count_time(fun):
# def inner():
# start=time.time()
# fun()
# end=time.time()
# print(f'用时{end-start}秒')
# return inner
#
# # 装饰器在装饰函数时的原理
# show=count_time(show)
# show()
# 定义装饰器(语法糖)
def count_time(fun): # 必须要有一个参数接收被装饰函数
def inner():
start=time.time()
fun()
end=time.time()
print(f'用时{end-start}秒')
return inner
# 装饰器写法:@闭包的外部函数,必须在闭包定以后使用
print('解析装饰器1')
@count_time # 解释成show=count_time(show),show指向count_time函数中的inner
def show():
n=0
for i in range(10000000):
n+=i
print('show_',n)
print('解析装饰器2')
@count_time # 解释成display=count_time(display)
def display():
print('Display')
print('正式执行...')
show()
display()
2.装饰器的通用类型的定义
(当被装饰函数有参数或者有返回值时同样适用)
'''
装饰器的通用类型的定义(当被装饰函数有参数或者有返回值时同样适用)
'''
def outer(func):
def inner(*args,**kwargs): # *为元组和列表解包,**为字典解包
print('*'*30)
print(args,kwargs)
ret=func(*args,**kwargs) # 解包,否则形参是元组或字典
print('*'*30)
return ret
return inner
@outer
def show(name,msg):
return str(name)+' say: '+str(msg)
print(show('Tom',msg='Hello'))
3.多个装饰器同时装饰一个函数
# 第一个闭包
def wrapper_div(func):
def inner(*args,**kwargs):
return '<div>'+func(*args,**kwargs)+'</div>'
return inner
# 第二个闭包
def wrapper_p(func):
def inner(*args,**kwargs):
return '<p>'+func(*args,**kwargs)+'</p>'
return inner
# 从下往上装饰,从上往下执行
@wrapper_div
@wrapper_p
# 定义一个函数
def show():
return 'Short life I use Python.'
print(show()) #<div><p>Short life I use Python.</p></div>
4.多个装饰器同时装饰一个函数(二)
def outer1(func):
def inner():
print('装饰器1-1')
func()
print('装饰器1-2')
return inner
def outer2(func):
def inner():
print('装饰器2-1')
func()
print('装饰器2-2')
return inner
'''
1.show指向outer1.inner
2.outer1.inner.func指向outer2.inner
3.outer2.inner.func指向show
'''
@outer1
@outer2
def show():
print('Show...')
show()
5.类装饰器使用方法
import time
class Wrapper():
def __init__(self,func):
self.func=func
# 当类中实现了此方法时,该类的实例对象就变成了可调用对象,即可以在实例对象后面加()
def __call__(self, *args, **kwargs):
print('装饰内容1...')
start=time.time()
ret=self.func(*args,**kwargs)
end=time.time()
print(f'执行了{end-start}秒')
print('装饰内容2...')
return ret
该装饰器执行完成后,被装饰函数指向该类的实例对象
如果让被装饰函数执行,那么在类中要添加__call__方法,相当于闭包格式中的内函数
一旦被装饰函数执行调用,那么就会去执行实例对象中的__call__函数
@Wrapper #解释成show=Wrapper(show),show变成了类的一个对象
def show():
print('Show...')
show()
6.装饰器带有参数(使用带有参数的装饰器,其实是在装饰器外面又包裹了一个函数)
# @Author : Kant
# @Time : 2022/1/23 22:43
def set_args(msg):
def outer(func):
def inner():
print('装饰内容',msg)
func()
return inner
return outer
'''
使用带有参数的装饰器,其实是在装饰器外面又包裹了一个函数,使用该函数接收参数,返回的是装饰器
调用set_args()后会返回outer的地址引用,变成了@outer
'''
@set_args('Hello')
# 无论闭包函数写成什么样子,被装饰函数永远指向闭包函数的内函数
def show():
print('Show...')
show()
6.使用装饰器实现自动维护路由表
路由功能:通过请求的路径,可以找到资源的地址
# 定义一个路由表字典
router_table={}
def router(url):
def wrapper(func):
def inner():
print('1')
print('inner-',func) # 查看当前的被装饰函数是谁
func()
# 在这里维护路由表字典
router_table[url]=inner # 如果写func,inner函数中的内容都不会执行
print('路由表字典:',router_table)
return inner
return wrapper
@router('index.html')
def index():
print('首页内容')
@router('center.html')
def center():
print('个人中心')
@router('mail.html')
def mail():
print('邮箱页面')
@router('login.html')
def login():
print('登录页面')
def error():
print('访问页面不存在')
def request_url(url):
func=error
if url in router_table:
func=router_table[url]
func()
print('开始执行函数')
request_url('index.html')
request_url('center.html')
request_url('mail.html')
request_url('test.html')
request_url('login.html')
来源:https://kantlee.blog.csdn.net/article/details/122684743


猜你喜欢
- 8大基础定位driver.find_element_by_id() # id定位driver.find_element_by_name()
- 但是,当一本书学过之后,对一般的技术和函数都有了印象,突然想要查找某个函数的实例代码时,却感到很困难,因为一本书的源代码目录很长,往往有几十
- PDOStatement::fetchColumnPDOStatement::fetchColumn — 从结果集中的下一行返回单独的一列。
- Python PyTorch深度学习框架PyTorch是一个基于Python的深度学习框架,它支持使用CPU和GPU进行高效的神经网络训练。
- 1下载安装1.1打开官网http://www.jetbrains.com/pycharm/download/耐心等待,大概200M,几分钟左
- 本文实例讲述了Python基于回溯法子集树模板解决马踏棋盘问题。分享给大家供大家参考,具体如下:问题将马放到国际象棋的8*8棋盘board上
- java后台相关问题一,程序包lombok不存在通常报这个错误,是因为,我们的开发者工具idea没有安装lombok库导致的解决办法如下:提
- 上图代码# -*- coding: utf-8 -*-"""Created on Sun Jun 18 20:
- jQuery的选择器可谓异常强大,没有什么DOM里的任何数据能逃出它的掌心,这点是我非常喜欢的,以前获取NODE要用getElementBy
- 简介序列化的目的是方便数据的传输和存储,在PHP中,序列化和反序列化一般用做缓存,比如session缓存,cookie等。反序列化中常见的魔
- 获取不带扩展名的文件的名称:import osprintos.path.splitext("path_to_file")
- 要随机生成字符串代码如下: 在MySQL中定义一个随机串的方法,然后再SQL语句中调用此方法。 随机串函数定义方法: CREATE DEFI
- 1 简介二进制日志,记录对数据发生或潜在发生更改的SQL语句,并以二进制形式保存在磁盘。2 Binlog 的作用主要作用:复制、恢复和审计。
- 开发自定义Web框架接收web服务器的动态资源请求,给web服务器提供处理动态资源请求的服务。根据请求资源路径的后缀名进行判断:如果请求资源
- 方法一:var tableInit = table.render({ elem:
- 公式如下:rand() * (y-x) + x咱们学php的都知道,随机函数rand或mt_rand,可以传入一个参数,产生0到参数之间的随
- BULK INSERT以用户指定的格式复制一个数据文件至数据库表或视图中。 语法:BULK INSERT [ [ 'database
- 1 概述利用Python生成简单的词云,需要的工具是cython,wordcloud与anaconda.2 准备工作包括安装cython,w
- 有时候我们会有这样的一个需求:我们定义了一个 Python 的方法,方法接收一些参数,但是调用的时候想将这些参数用命令行暴露出来。比如说这里
- 一、前言 axios的封装和api接口的统一管理,其实主要目的就是在帮助我们简化代码和利于后期的更新维护。二、axios封装步骤安