python3 装饰器参数_Learn Python 3:装饰器

一、理解装饰器

通俗点说,当我们想给一个函数增强额外的功能,但又不想修改原函数的定义,同时新增的功能其它函数可能也需要使用,装饰器就是来解决这种需求的,将与原函数功能无关的代码提取出来,实现复用,在代码运行期间动态的给原函数增加功能,例如在函数执行前后插入日志、计算函数的执行时间等等

二、实践

1、一个小需求

有一个需求,要在函数执行前后打印start execute、end execute,如果我们还不知道有装饰器存在可以怎么做呢?

首先定义原函数:

def my_func():

print('Hello World')

再定义一个函数用来打印日志,并在其中执行原函数:

def log(func):

def wrapper():

print('start execute')

func()

print('end execute')

return wrapper

可以看到,log函数接收一个函数作为参数,并返回一个新的wrapper函数。

最后看执行结果:

my_func = log(my_func)

my_func()

0

我们将my_func函数作为参数传给log函数,并将返回的wrapper函数赋值给my_func变量,则my_func变量就是返回的wrapper函数,并不是之前定义的my_func函数,最后执行my_func()其实执行的是返回的wrapper函数。到这里已经实现了前边的小需求,其实装饰器的原理亦是如此。

2、使用装饰器

如果使用装饰器怎么写呢?先不需要修改log函数,只对my_func函数做修改:

@log

def my_func():

print('Hello World')

很明显吧,用Python的 @ 语法实现装饰器,实现log函数对my_func函数的装饰。

再看执行结果:

1

其实装饰器相当于替我们执行了my_func = log(my_func)这一步。

但是有个问题,按理my_func函数的__name__属性应该是my_func,但使用装饰器后变成了wrapper:

2

其实就是前边讲的赋值操作my_func = log(my_func)导致的,这当然不是我们想看到的,可以用Python内置functools模块的wraps()方法,修改我们的log函数:

def log(func):

@functools.wraps(func)

def wrapper():

print('start execute')

func()

print('end execute')

return wrapper

再执行结果:

3

3、带参数的被装饰函数

如果my_func函数有参数呢?像这样:

def my_func(a, b):

print('a+b=%d' % (a + b))

当然还要修改log函数,怎么改呢,这样???给wrapper加两个参数???

def log(func):

@functools.wraps(func)

def wrapper(a, b):

print('start execute')

func(a, b)

print('end execute')

return wrapper

如果其它函数的参数个数、参数形式和my_func不同,也想使用log作为装饰器,那这样修改log肯定不行......,可以这样,让装饰器内嵌的wrapper函数支持可变参数以及关键字参数:

def log(func):

@functools.wraps(func)

def wrapper(*args, **kw):

print('start execute')

func(*args, **kw)

print('end execute')

return wrapper

这样其它函数也就能共用这个log函数了,要不然还搞啥装饰器。现在使用修改后的log函数:

@log

def my_func(a, b):

print('a+b=%d' % (a + b))

再来一个my_func1函数:

@log

def my_func1(a, b, c, *, d):

print('a+b+c+d=%d' % (a + b + c + d))

看下执行结果:

4

以my_func为例,这时候使用装饰器执行my_func(1, 2)相当于执行了log(my_func)(1, 2)。

4、带参数的装饰器函数

如果装饰器函数本身也需要参数呢?继续以log函数为例,现在需要接受一个字符串为参数,并在被装饰函数执行前打印,则可以给它在内嵌一层函数:

def log(arg):

def decorator(func):

@functools.wraps(func)

def wrapper(*args, **kw):

print('装饰器的参数:%s' % arg)

print('start execute')

func(*args, **kw)

print('end execute')

return wrapper

return decorator

这时再给my_func添加装饰器:

@log('Hello World')

def my_func(a, b):

print('a+b=%d' % (a + b))

执行结果如下:

5

此时相当于执行了log('Hello World')(my_func)(1, 2)

5、参数可选的装饰器函数

我们继续扩展装饰器函数log的功能,使其既支持:

@log('Hello World')

def my_func(a, b):

print('a+b=%d' % (a + b))

又要支持:

@log

def my_func(a, b):

print('a+b=%d' % (a + b))

即参数可选,怎么修改呢?前边已经说过了,第一种情况执行my_func(1, 2)相当于log('Hello World')(my_func)(1, 2),其中log('Hello World')先执行,返回接受my_func为参数的decorator函数,第二种情况执行相当于log(my_func)(1, 2),其中log(my_func)先执行,返回的是接受1、2为参数的wrapper函数。所以我们让log函数在两种情况下分别返回不同的函数,即log函数的参数为函数时其返回wrapper函数,即decorator(arg),log函数的参数为字符串时让其返回decorator函数,至于打印log的字符串参数,只需要判参数是字符串再打印即可:

def log(arg):

def decorator(func):

@functools.wraps(func)

def wrapper(*args, **kw):

if arg and isinstance(arg, str):

print('装饰器的参数:%s' % arg)

print('start execute')

func(*args, **kw)

print('end execute')

return wrapper

if callable(arg):

return decorator(arg)

return decorator

1、isinstance(arg, str):判断arg是否为str类型

2、callable(arg):判断arg是否可被调用,可被调用指的是能否使用()括号的方法调用。

测试结果如下:

6

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/417589.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

android 三星 白色,时尚实用都拥有 白色Android手机盘点

唯美大气:三星I9000三星I9000的高人气不用多说,许多人在看过了黑色之后也等待着白色版本的上市。而在上周该机的白色版本也终于到来,赶在圣诞节之前为我们提供了多一种的白色Android机型选择。从图片中可以看出I9000机身正面依旧为黑色&#…

XidianOJ 1099 A simple problem

题目描述 一个长度为N的数组A&#xff0c; 所有数都是整数 &#xff0c;0 < A[i] < 1000000&#xff0c;1 < i < N&#xff0c;1 < N < 100000&#xff0c;对于 任意i&#xff0c;j &#xff0c;1 < i < j < N&#xff0c;[i&#xff0c; j]中所…

C字符操作函数大全

函数名: stpcpy 功 能: 拷贝一个字符串到另一个 用 法: char *stpcpy(char *destin, char *source); 程序例: #include <stdio.h> #include <string.h> int main(void) { char string[10]; char *str1 "abcdefghi"; stpcpy(string, str1); …

见微知著(一):解析ctf中的pwn--Fast bin里的UAF

在网上关于ctf pwn的入门资料和writeup还是不少的&#xff0c;但是一些过渡的相关知识就比较少了&#xff0c;大部分赛棍都是在不断刷题中总结和进阶的。所以我觉得可以把学习过程中的遇到的一些问题和技巧总结成文&#xff0c;供大家参考和一起交流。当然&#xff0c;也不想搞…

python语言学完后学什么_学完Python语言可以做什么?发展前景怎么样?

Python是一门高级的编程语言&#xff0c;其语言功能强大、语法简单、上手容易&#xff0c;因此受到了不少人的喜欢。而对于学习一门语言&#xff0c;很多人最看重的就是&#xff0c;学习之后可以做什么?有哪些岗位?薪资待遇如何?为大家详细的讲解一下。Python是一门面向对象…

火狐插件 打开html 死机,火狐flash插件崩溃(Firefox火狐Flash插件卡死问题完美解决方法)...

火狐flash插件崩溃(Firefox火狐Flash插件卡死问题完美解决方法)&#xff0c;哪吒游戏网给大家带来详细的火狐flash插件崩溃(Firefox火狐Flash插件卡死问题完美解决方法)介绍&#xff0c;大家可以阅读一下&#xff0c;希望这篇火狐flash插件崩溃(Firefox火狐Flash插件卡死问题完…

C#关键字(79个)

abstract&#xff1a;标识一个可以扩展但不能被实体化得、必须被实现得类或方法&#xff1b; as&#xff1a;一个转换操作符&#xff0c;如果转化失败&#xff0c;就返回null&#xff1b; base&#xff1a;用于访问被派生类或构造中得同名成员隐藏的基类成员&#xff1b; bool&…

Atitti 大话存储读后感 attilax总结

Atitti 大话存储读后感 attilax总结 1.1. 大话存储中心思想&#xff08;主要讲了磁盘文件等存储&#xff09;1 1.2. 最耐久的存储&#xff0c;莫过于石头了&#xff0c;要想几千万年的存储信息&#xff0c;使用石头是最好的方式了1 1.3. 数据传输机制&#xff1a;总线机制1 1.4…

.Net System.Object类介绍

每个类型最终都要继承自System.Object类型&#xff08;默认情况下是隐式继承&#xff09;System.Object类型的公有方法&#xff1a;Equals&#xff1a;静态成员。已重载。 确定两个 Object 实例是否相等。返回True。ReferenceEquals&#xff1a;静态成员。确定指定的 Object 实…

uuid表示时间的部分_技术译文 | UUID 很火但性能不佳?今天我们细聊一聊

作者&#xff1a;Yves Trudeau Yves 是 Percona 的首席架构师&#xff0c;专门研究分布式技术&#xff0c;例如 MySQL Cluster&#xff0c;Pacemaker 和 XtraDB cluster。他以前是 MySQL 和 Sun 的高级顾问。拥有实验物理学博士学位。原文链接&#xff1a;https://www.percona.…

西电计算机科学院实践中心,计算机基础教学实验中心

一、总体情况计算机基础教学实验中心隶属于计算机网络与信息安全国家级实验教学示范中心&#xff0c;承担着全校本科生的计算机基础教学和实验任务&#xff0c;是学校对外的重要窗口。中心总面积4200平方米&#xff0c;固定资产总价值接近1500万元&#xff0c;仪器设备共3907台…

jquery通过attr取html里自定义属性原来这么方便啊

<script type"text/javascript"> function fangGouWuChe(obj) { //放入购物车 var sMat $(obj).parent().parent().parent().parent().attr("material"); var sPrice $(obj).parent().parent().find(em[class"sale-price"]).text(); …

Abbirb120型工业机器人_ABB IRB 120工业机器人.pdf

ABB IRB 120工业机器人IRB 120工业机器人-ABB最小机器人&#xff0c;紧凑柔性生产的理想之选IRB 120小型工业机器人是ABB新型第四代机器人家族的最新成员&#xff0c;也是迄今为止ABB制造的最小机器人。IRB 120具有敏捷、紧凑、轻量的特点&#xff0c;控制精度与路径精度俱优&a…

html4废弃了哪些元素,HTML中的一些废弃元素_html

如果我们在进行css网页布局的时候&#xff0c;还在使用被W3C废弃的元素&#xff0c;那就失去了使用CSS的意义&#xff0c;虽然它们可能同样被样式控制。在Xhtml中不再使用HTML中的一些废弃元素。它们主要有以下一些。Elements and attributes that have been deprecated in the…

vs2010编写的net3.5用vs2008打开

*.sln解决方案文件将Microsoft Visual Studio Solution File, Format Version 11.00改为Microsoft Visual Studio Solution File, Format Version 10.00 *.csproj项目文件网站项目需要修改,类库项目可以直接打开有<Import Project"$(MSBuildExtensionsPath32)\Microsof…

r语言rank降序_R语言rank函数详细解析

1.rank函数是什么rank相关文档[1]可以译为"返回原数组(?)中各个元素排序(?)后的秩次(?)"&#xff0c;表面上看确实可以得到次序&#xff0c;但对数组、排序、秩次交待不清。2.rank函数使用情景比如&#xff0c;在100米赛跑中&#xff0c;甲乙丙三人的成绩为6.8s, …

计算机时代 英语,雅思8分范文:计算机时代教师角色 【出国英语】

雅思8分范文&#xff1a;计算机时代教师角色 【出国英语】The computer are widely used in education and some people think teacher are not play important role in the classroom .to what extend do you agree? (agree/disagree)医学教育网nowadays, the computer is ra…

C# 列出进程以及详细信息

建立一个listBox将进程名称遍历进去 this.listBox1.Items.Clear();Process[] MyProcessesProcess.GetProcesses();foreach(Process MyProcess in MyProcesses){this.listBox1.Items.Add(MyProcess.ProcessName);}this.listBox1.SelectedIndex0; 选中listBox里面的项后将进程详…

Nginx配置文件(nginx.conf)配置详解

Nginx的配置文件nginx.conf配置详解如下&#xff1a; user nginx nginx ; Nginx用户及组&#xff1a;用户 组。window下不指定 worker_processes 8; 工作进程&#xff1a;数目。根据硬件调整&#xff0c;通常等于CPU数量或者2倍于CPU。 error_log logs/error.log; error_log…