什么是Python装饰器?如何定义和使用?


Posted in Python onApril 11, 2022

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')
Python 相关文章推荐
Python的Django框架可适配的各种数据库介绍
Jul 15 Python
Python机器学习logistic回归代码解析
Jan 17 Python
Python操作Sql Server 2008数据库的方法详解
May 17 Python
详谈Pandas中iloc和loc以及ix的区别
Jun 08 Python
python学生信息管理系统(初级版)
Oct 17 Python
详解pyenv下使用python matplotlib模块的问题解决
Nov 29 Python
Pandas库之DataFrame使用的学习笔记
Jun 21 Python
Python3远程监控程序的实现方法
Jul 15 Python
Tensorflow模型实现预测或识别单张图片
Jul 19 Python
python numpy之np.random的随机数函数使用介绍
Oct 06 Python
用Python实现校园通知更新提醒功能
Nov 23 Python
分享PyCharm最新激活码(真永久激活方法)不用每月找安装参数或最新激活码了
Dec 27 Python
Python经常使用的一些内置函数
python处理json数据文件
Python几种酷炫的进度条的方式
Python通过loop.run_in_executor执行同步代码 同步变为异步
Python Pandas解析读写 CSV 文件
宝塔更新Python及Flask项目的部署
python模板入门教程之flask Jinja
You might like
浅析php中jsonp的跨域实例
2013/06/21 PHP
PHP定时任务延缓执行的实现
2014/10/08 PHP
firefox下input type=&quot;file&quot;的size是多大
2011/10/24 Javascript
javascript学习笔记(十七) 检测浏览器插件代码
2012/06/20 Javascript
javascript loadScript异步加载脚本示例讲解
2013/11/14 Javascript
jQuery中scrollLeft()方法用法实例
2015/01/16 Javascript
使用jQuery制作浮动工具栏的实例分享
2016/05/13 Javascript
js 点击a标签 获取a的自定义属性方法
2016/11/21 Javascript
input获取焦点时底部菜单被顶上来问题的解决办法
2017/01/24 Javascript
基于JavaScript实现复选框的全选和取消全选
2017/02/09 Javascript
详解NodeJS框架express的路径映射(路由)功能及控制
2017/03/24 NodeJs
vue分类筛选filter方法简单实例
2017/03/30 Javascript
vue.js todolist实现代码
2017/10/29 Javascript
vue 实现的树形菜的实例代码
2018/03/19 Javascript
jQuery+Ajax+js实现请求json格式数据并渲染到html页面操作示例
2020/06/02 jQuery
prettier自动格式化去换行的实现代码
2020/08/25 Javascript
基于JQuery和DWR实现异步数据传递
2020/10/16 jQuery
js实现淘宝浏览商品放大镜功能
2020/10/28 Javascript
Python multiprocessing.Manager介绍和实例(进程间共享数据)
2014/11/21 Python
在Python中封装GObject模块进行图形化程序编程的教程
2015/04/14 Python
Python 中的with关键字使用详解
2016/09/11 Python
Django自定义分页效果
2017/06/27 Python
Python 在字符串中加入变量的实例讲解
2018/05/02 Python
Python基础之高级变量类型实例详解
2020/01/03 Python
Python3 Tensorlfow:增加或者减小矩阵维度的实现
2020/05/22 Python
Python如何实现的二分查找算法
2020/05/27 Python
详解如何修改python中字典的键和值
2020/09/29 Python
html5 浏览器支持 如何让所有的浏览器都支持HTML5标签样式
2012/12/07 HTML / CSS
美国最大点评网站:Yelp
2018/02/14 全球购物
澳大利亚买卖正宗二手奢侈品交易平台:Luxe.It.Fwd
2019/10/16 全球购物
校本教研工作制度
2014/01/22 职场文书
母婴店促销方案
2014/03/05 职场文书
感恩教育活动总结
2014/05/05 职场文书
2019年警察入党转正申请书最新范文
2019/09/03 职场文书
纯CSS3实现div按照顺序出入效果
2021/07/15 HTML / CSS
在虚拟机中安装windows server 2008的图文教程
2022/06/28 Servers