python3 如何给装饰器传递参数
【引子】
之前写过一篇文章用来讲解装饰器(https://www.cnblogs.com/JiangLe/p/9309330.html) 、那篇文章的定位是入门级的
所以也就没有讲过多的高级主题,决定在这里讲一下如果为装饰器传递参数
【目标】
我们有两个函数“add_fun”、“add” 其中“add_fun”已经过时、如果用户有调用这个函数的话就提示它“add_fun”已经过时并且引导
它去调用“add”函数
【add\add_fun函数的定义】
def add_fun(x,y):
"""
实现两个数相加、并返回合
"""
return x+y def add(x,y):
"""
实现两个数相加、并返回合
"""
return x+y
【通过装饰器引导调用add_fun的用户去调用add】
def deprecated(fun,new_fun_name):
"""deprecated函数会返回一个叫inner的函数、inner函数会返回
fun调用的结果,与直接调用fun得到值不同的是inner会先打印一行提示
表明fun已经过时
"""
def inner(x,y):
print("{fun.__name__} 函数已经过时 请使用{new_fun_name}".format(fun=fun,new_fun_name=new_fun_name))
return fun(x,y)
return inner def add_fun(x,y):
"""
实现两个数相加、并返回合
"""
return x+y add_fun = deprecated(add_fun,'add') def add(x,y):
"""
实现两个数相加、并返回合
"""
return x+y if __name__=="__main__":
print(add_fun(1,1))
调用时的输出如下:
python3 dc.py
add_fun 函数已经过时 请使用add
【难道为装饰器增加参数就这么的简单】
仔细的你可能已经发现了、我们在上面的代码里并没有用装饰器的语法糖衣、而是通过函数调用的方式来包装的add_fun方法
add_fun = deprecated(add_fun,'add')
机智的你应该想到了@deprecated('add') 这样去装饰add_fun应该也能成吧!于是代码如下(关键代码)
@deprecated('add')
def add_fun(x,y):
"""
实现两个数相加、并返回合
"""
return x+y
当你调用时会发现完全不是你想要的那样、
python3 dc.py
Traceback (most recent call last):
File "dc.py", line , in <module>
@deprecated('add')
TypeError: deprecated() missing required positional argument: 'new_fun_name'
事实上目前语法糖衣只解决了最简单的情况、如果你要给@写法 指定参数还要另寻它法。
【真理简洁而有力】
linux的世界里有句话“一切皆文件”,python的世界里也有一句话“一切皆对象”; 但是关键不是会“背”,而是“领悟”。
一个经典的糖衣格式是这样的
@decorate
def fun():
pass
请仔细看一下不难发现@后面直接是对象名、由python的数据模式可知、对象名只是一个对象的标识;也就是说@后面是一个对象!对象可以
是已经定义好的,也可以是调用才生成。明白这一层道理之后事情就比较好办了,我们只要在调用时生成“装饰”对象就可以了,因为要调用
所以就给了我们传递参数的机会。
【触摸真理一】
用调用时生成的对象用作装饰器
def deprecated(new_fun_name):
"""derepcated 装饰器把函数标记为过时
"""
def warpper(fun):
"""
"""
def inner(*args):
print("{0} 函数已经过时 请使用 {1}".format(fun.__name__,new_fun_name))
return fun(*args)
return inner return warpper decorator = deprecated('add') # 特意把这一步单独分离出来、用于说明什么叫调用时创建的对象用作做装饰器 @decorator # 特意把这一步单独分离出来、用于说明什么叫调用时创建的对象用作做装饰器
def add_fun(x,y):
"""
实现两个数相加、并返回合
"""
return x+y def add(x,y):
"""
实现两个数相加、并返回合
"""
return x+y if __name__=="__main__":
print(add_fun(1,1))
【触摸真理二】
与语法糖衣结合、完成传递参数的目的
def deprecated(new_fun_name):
"""derepcated 装饰器把函数标记为过时
"""
def warpper(fun):
"""
"""
def inner(*args):
print("{0} 函数已经过时 请使用 {1}".format(fun.__name__,new_fun_name))
return fun(*args)
return inner return warpper @deprecated('add')
def add_fun(x,y):
"""
实现两个数相加、并返回合
"""
return x+y def add(x,y):
"""
实现两个数相加、并返回合
"""
return x+y if __name__=="__main__":
print(add_fun(1,1))
调用时输出如下
python3 dc.py
add_fun 函数已经过时 请使用 add
总结:
如果只能用一名话概括python我想对简洁的应该是“一切皆对象”了吧。
python3 如何给装饰器传递参数的更多相关文章
- python 装饰器 传递参数简单案例
def debug(func): def wrapper(*args, **kwargs): # 指定宇宙无敌参数 print "[DEBUG]: enter {}()".form ...
- 装饰器,装饰器多参数的使用(*arg, **kwargs),装饰器的调用顺序
一.#1.执行outer函数,并且将其下面的函数名,当作参数 #2.将outer的返回值重新赋值给f1 = outer的返回值 #3.新f1 = inner #4.func = 原f1 #!/usr/ ...
- typescript装饰器 方法装饰器 方法参数装饰器 装饰器的执行顺序
/* 装饰器:装饰器是一种特殊类型的声明,它能够被附加到类声明,方法,属性或参数上,可以修改类的行为. 通俗的讲装饰器就是一个方法,可以注入到类.方法.属性参数上来扩展类.属性.方法.参数的功能. 常 ...
- python_如何修改装饰器中参数?
案例: 为分析程序内哪些函数执行时间开销较大,我们需定义一个带timeout参数的装饰器 需求: 统计被装饰函数的运行时间 时间大于timeout时,将此次函数调用记录到log日志中 运行时可以修改t ...
- Python学习第四十一天函数装饰器传参数的用法
在不改变函数的结构的基础,我们给函数加新的功能,用是函数装饰器,如果要给函数传递参数,那么应该怎么做呢 @timerdef test2(name,age): time.sleep(3) print(' ...
- 笔记||Python3进阶之装饰器
# 装饰器# 特征: 是用一个@开头的字符串# 装饰器通常用来装饰函数.或者类的方法# 被装饰后的函数,通常是在原有的函数基础上,会多出增加一点功能# 一般来说装饰器本身也是一个函数## def te ...
- python3 进一步了解装饰器 NLP第四条
还是先来抄一段NLP第四条: 四,只有感官经验塑造出来的世界,没有绝对的真实世界 每个人运用自己的感觉器官把资料摄入(摄入过程),由于感官运用是主观地有选择性的,因此不能,亦不需要把所有资料捕获. ...
- 【python3】 函数 装饰器
第一步 : 了解装饰器 装饰器模式,重点在于装饰,装饰的核心仍是被装饰的对象. 举一个栗子:我今天穿了一件短袖,但是突然一阵风,短袖没办法为我御寒,我想到的办法是将短袖变得更厚更长,但是改造之后,它就 ...
- Python3基础笔记--装饰器
装饰器是十二分重要的高级函数. 参考博客:装饰器 所需前提知识: 1.作用域: LEGB 2.高阶函数 高阶函数是至少满足下列一个条件的函数: 1)接受一个或多个函数作为输入 2)输出一个函数 注意理 ...
随机推荐
- JS 处理Json数据事例
JS从远端获取数据之后,往往还需要在处理一下,下面给出一个事例,供参考 将'[{"role_id":1,"enable":1},{"role_id&q ...
- 算法笔记_220:猜算式(Java)
目录 1 问题描述 2 解决方案 1 问题描述 看下面的算式: □□ x □□ = □□ x □□□ 它表示:两个两位数相乘等于一个两位数乘以一个 三位数. 如果没有限定条件,这样的例子很多. 但 ...
- C语言操作Redis总结
#include "hiredis.h" #define NO_QFORKIMPL #pragma comment(lib,"hiredis.lib") #pr ...
- SSM实战——秒杀系统之创建项目、管理依赖、设计数据库
注:本项目使用Myeclipse开发. 一:项目创建 1:使用Myeclipse创建一个web project,命名为MySeckill,并转换为Maven项目. 2:创建项目文件目录如下: 上面四个 ...
- Shell编程初步
一:Hello World 新建一个文件,命名时以 .sh 为后缀.每个bash文件开头第一行表名文件类型: #!/bin/bash 然后在下面输入代码. 比如输出hello world: #!/ ...
- 整合Tomcat和Nginx实现动静态负载均衡
转载请注明原文地址:http://www.cnblogs.com/ygj0930/p/6386135.html Nginx与tomcat整合可以实现服务器的负载均衡. 在用户的请求发往服务器进行处理时 ...
- jump-game i&&ii 能否跳出区间 贪心
I: Given an array of non-negative integers, you are initially positioned at the first index of the a ...
- Android开发之欢迎界面标准
import java.util.ArrayList; import android.app.Activity; import android.content.SharedPreferences; i ...
- windows下命令行终端使用rz上传文件参数详解
rz命令: (X) = option applies to XMODEM only (Y) = option applies to YMODEM only (Z) = option applies t ...
- Java中的Random()函数 【转载】
今天在做Java练习的时候注意到了Java里面的一个随机函数——Random,刚开始只是知道这个函数具有随机取值的作用,于是上网搜索了资料一番,做了一下一些关于Random函数的总结: J ...