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)输出一个函数 注意理 ...
随机推荐
- AOP技术分析
AOP的概述(http://www.cnblogs.com/lxp503238/p/6837653.html) 1. 什么是AOP的技术? * 在软件业,AOP为Aspec ...
- Python学习笔记六:文件处理
一:打开文件 open(name,mode,[bufferSize]) name:文件路径 mode:文件打开方式 二:文件读取 read()方法:可以一次读取文件的全部内容,Python把内容读到内 ...
- Java多线程之ReadWriteLock读写锁简介与使用教程
转载请注明原文地址:http://www.cnblogs.com/ygj0930/p/6558073.html 普通的锁在对某一内容加锁后,其他线程是不能访问的.但是我们要考虑这种情况:如果当前加锁 ...
- Linux下使用logrotate实现日志切换
运维过程中经常会发现一些 C 程序,每天会生产这样的日志: /home/admin/app_name/logs/access_log 那么天长地久,如果这个程序不会自动去轮转这个日志,那么这个日志文件 ...
- 令Django 视图有默认 login_required
方法一 from django.template import RequestContext from django.shortcuts import render_to_response from ...
- Dom4j操作XML实战,解析和插入XML实例
本例子是用XML来代替数据库的,XML的每个节点代替数据库一行数据. 直说过程: XML文件结构:定义了一个名为:User.xml的文件: <?xml version="1.0&quo ...
- Centos6.5卸载图形化
问题描述: Centos6.5想运行在非图形化状态,减小系统资源的开销!提升服务器性能....... 问题解决: 01.切换运行模式,变相实现非图形化运行 多用户模式 init 图形化模式 init ...
- ios中文件下载(带缓存)
使用asiHttPRequst框架 封装下载类 #import <Foundation/Foundation.h> #define FILESDOWNLOADCOMPLETE @" ...
- ios 中sqlite的用法
#import <sqlite3.h> @interface ViewController () { sqlite3 *_sqldb; } @end @implementation Vie ...
- HDUOJ-----Robot Motion
Robot Motion Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Tota ...