0

0

python 装饰器详解

藏色散人

藏色散人

发布时间:2020-02-13 11:41:20

|

5295人浏览过

|

来源于php中文网

原创

python 装饰器详解

python装饰器详解

python装饰器的详细解析

什么是装饰器?

推荐学习:Python视频教程

python装饰器(fuctional decorators)就是用于拓展原来函数功能的一种函数,目的是在不改变原函数名(或类名)的情况下,给函数增加新的功能。 

立即学习Python免费学习笔记(深入)”;

这个函数的特殊之处在于它的返回值也是一个函数,这个函数是内嵌“原“”函数的函数。

一般而言,我们要想拓展原来函数代码,最直接的办法就是侵入代码里面修改,例如:

import time
def f():
    print("hello")
    time.sleep(1)
    print("world")  

 

这是我们最原始的的一个函数,然后我们试图记录下这个函数执行的总时间,那最简单的做法就是改动原来的代码:

import time
def f():
    start_time = time.time()
    print("hello")
    time.sleep(1)
    print("world")
    end_time = time.time()
    execution_time = (end_time - start_time)*1000
    print("time is %d ms" %execution_time)

 

但是实际工作中,有些时候核心代码并不可以直接去改,所以在不改动原代码的情况下,我们可以再定义一个函数。(但是生效需要再次执行函数)

import time
def deco(func):
    start_time = time.time()
    f()
    end_time = time.time()
    execution_time = (end_time - start_time)*1000
    print("time is %d ms" %execution_time)
def f():
    print("hello")
    time.sleep(1)
    print("world")
if __name__ == '__main__':
    deco(f)
    print("f.__name__ is",f.__name__)
    print()

 

这里我们定义了一个函数deco,它的参数是一个函数,然后给这个函数嵌入了计时功能。但是想要拓展这一千万个函数功能,

就是要执行一千万次deco()函数,所以这样并不理想!接下来,我们可以试着用装饰器来实现,先看看装饰器最原始的面貌。 

import time
def deco(f):
    def wrapper():
        start_time = time.time()
        f()
        end_time = time.time()
        execution_time = (end_time - start_time)*1000
        print("time is %d ms" %execution_time )
    return wrapper
@deco
def f():
    print("hello")
    time.sleep(1)
    print("world")
if __name__ == '__main__':
    f()

 

这里的deco函数就是最原始的装饰器,它的参数是一个函数,然后返回值也是一个函数。

其中作为参数的这个函数f()就在返回函数wrapper()的内部执行。然后在函数f()前面加上@deco,

f()函数就相当于被注入了计时功能,现在只要调用f(),它就已经变身为“新的功能更多”的函数了,

(不需要重复执行原函数)。 

扩展1:带有固定参数的装饰器

Android WebView实例详解 中文WORD版
Android WebView实例详解 中文WORD版

本文档主要讲述的是Android WebView实例详解;Android手机中内置了一款高性能webkit内核浏览器,在SDK中封装为一个叫做WebView组件。 WebKit是Mac OS X v10.3及以上版本所包含的软件框架(对v10.2.7及以上版本也可通过软件更新获取)。 同时,WebKit也是Mac OS X的Safari网页浏览器的基础。WebKit是一个开源项目,主要由KDE的KHTML修改而来并且包含了一些来自苹果公司的一些组件。希望本文档会给有需要的朋友带来帮助;感兴趣的朋友可以过来

下载
import time
def deco(f):
    def wrapper(a,b):
        start_time = time.time()
        f(a,b)
        end_time = time.time()
        execution_time = (end_time - start_time)*1000
        print("time is %d ms" % execution_time)
    return wrapper
@deco
def f(a,b):
    print("be on")
    time.sleep(1)
    print("result is %d" %(a+b))
if __name__ == '__main__':
    f(3,4)

扩展2:无固定参数的装饰器

import time
def deco(f):
    def wrapper(*args, **kwargs):
        start_time = time.time()
        f(*args, **kwargs)
        end_time = time.time()
        execution_time_ = (end_time - start_time)*1000
        print("time is %d ms" %execution_time)
    return wrapper
@deco
def f(a,b):
    print("be on")
    time.sleep(1)
    print("result is %d" %(a+b))
@deco
def f2(a,b,c):
    print("be on")
    time.sleep(1)
    print("result is %d" %(a+b+c))
if __name__ == '__main__':
    f2(3,4,5)
    f(3,4)

 

扩展3:使用多个装饰器,装饰一个函数

import time
def deco01(f):
    def wrapper(*args, **kwargs):
        print("this is deco01")
        start_time = time.time()
        f(*args, **kwargs)
        end_time = time.time()
        execution_time = (end_time - start_time)*1000
        print("time is %d ms" % execution_time)
        print("deco01 end here")
    return wrapper
def deco02(f):
    def wrapper(*args, **kwargs):
        print("this is deco02")
        f(*args, **kwargs)
        print("deco02 end here")
    return wrapper
@deco01
@deco02
def f(a,b):
    print("be on")
    time.sleep(1)
    print("result is %d" %(a+b))
if __name__ == '__main__':
    f(3,4)
'''
this is deco01
this is deco02
hello,here is a func for add :
result is 7
deco02 end here
time is 1003 ms
deco01 end here
'''

装饰器调用顺序

装饰器是可以叠加使用的,那么使用装饰器以后代码是啥顺序呢?

对于Python中的”@”语法糖,装饰器的调用顺序与使用 @ 语法糖声明的顺序相反。

在这个例子中,”f(3, 4) = deco01(deco02(f(3, 4)))”。

 

Python内置装饰器

在Python中有三个内置的装饰器,都是跟class相关的:staticmethod、classmethod 和property。

staticmethod 是类静态方法,其跟成员方法的区别是没有 self 参数,并且可以在类不进行实例化的情况下调用

classmethod 与成员方法的区别在于所接收的第一个参数不是 self (类实例的指针),而是cls(当前类的具体类型)

property 是属性的意思,表示可以通过通过类实例直接访问的信息

对于staticmethod和classmethod这里就不介绍了,通过一个例子看看property。

4f48ed1aace18c0f2b6e3ff6abeb6dd.png

注意,对于Python新式类(new-style class),如果将上面的 “@var.setter” 装饰器所装饰的成员函数去掉,则Foo.var 属性为只读属性,使用 “foo.var = ‘var 2′” 进行赋值时会抛出异常。但是,对于Python classic class,所声明的属性不是 read-only的,所以即使去掉”@var.setter”装饰器也不会报错。

总结

本文介绍了Python装饰器的一些使用,装饰器的代码还是比较容易理解的。只要通过一些例子进行实际操作一下,就很容易理解了。

相关文章

python速学教程(入门到精通)
python速学教程(入门到精通)

python怎么学习?python怎么入门?python在哪学?python怎么学才快?不用担心,这里为大家提供了python速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
C++ 单元测试与代码质量保障
C++ 单元测试与代码质量保障

本专题系统讲解 C++ 在单元测试与代码质量保障方面的实战方法,包括测试驱动开发理念、Google Test/Google Mock 的使用、测试用例设计、边界条件验证、持续集成中的自动化测试流程,以及常见代码质量问题的发现与修复。通过工程化示例,帮助开发者建立 可测试、可维护、高质量的 C++ 项目体系。

9

2026.01.16

java数据库连接教程大全
java数据库连接教程大全

本专题整合了java数据库连接相关教程,阅读专题下面的文章了解更多详细内容。

31

2026.01.15

Java音频处理教程汇总
Java音频处理教程汇总

本专题整合了java音频处理教程大全,阅读专题下面的文章了解更多详细内容。

14

2026.01.15

windows查看wifi密码教程大全
windows查看wifi密码教程大全

本专题整合了windows查看wifi密码教程大全,阅读专题下面的文章了解更多详细内容。

42

2026.01.15

浏览器缓存清理方法汇总
浏览器缓存清理方法汇总

本专题整合了浏览器缓存清理教程汇总,阅读专题下面的文章了解更多详细内容。

6

2026.01.15

ps图片相关教程汇总
ps图片相关教程汇总

本专题整合了ps图片设置相关教程合集,阅读专题下面的文章了解更多详细内容。

9

2026.01.15

ppt一键生成相关合集
ppt一键生成相关合集

本专题整合了ppt一键生成相关教程汇总,阅读专题下面的的文章了解更多详细内容。

6

2026.01.15

php图片上传教程汇总
php图片上传教程汇总

本专题整合了php图片上传相关教程,阅读专题下面的文章了解更多详细教程。

2

2026.01.15

phpstorm相关教程大全
phpstorm相关教程大全

本专题整合了phpstorm相关教程汇总,阅读专题下面的文章了解更多详细内容。

4

2026.01.15

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
最新Python教程 从入门到精通
最新Python教程 从入门到精通

共4课时 | 1.0万人学习

Django 教程
Django 教程

共28课时 | 3.1万人学习

SciPy 教程
SciPy 教程

共10课时 | 1.1万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号