引子

  之前写过一篇文章用来讲解装饰器(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 如何给装饰器传递参数的更多相关文章

  1. python 装饰器 传递参数简单案例

    def debug(func): def wrapper(*args, **kwargs): # 指定宇宙无敌参数 print "[DEBUG]: enter {}()".form ...

  2. 装饰器,装饰器多参数的使用(*arg, **kwargs),装饰器的调用顺序

    一.#1.执行outer函数,并且将其下面的函数名,当作参数 #2.将outer的返回值重新赋值给f1 = outer的返回值 #3.新f1 = inner #4.func = 原f1 #!/usr/ ...

  3. typescript装饰器 方法装饰器 方法参数装饰器 装饰器的执行顺序

    /* 装饰器:装饰器是一种特殊类型的声明,它能够被附加到类声明,方法,属性或参数上,可以修改类的行为. 通俗的讲装饰器就是一个方法,可以注入到类.方法.属性参数上来扩展类.属性.方法.参数的功能. 常 ...

  4. python_如何修改装饰器中参数?

    案例: 为分析程序内哪些函数执行时间开销较大,我们需定义一个带timeout参数的装饰器 需求: 统计被装饰函数的运行时间 时间大于timeout时,将此次函数调用记录到log日志中 运行时可以修改t ...

  5. Python学习第四十一天函数装饰器传参数的用法

    在不改变函数的结构的基础,我们给函数加新的功能,用是函数装饰器,如果要给函数传递参数,那么应该怎么做呢 @timerdef test2(name,age): time.sleep(3) print(' ...

  6. 笔记||Python3进阶之装饰器

    # 装饰器# 特征: 是用一个@开头的字符串# 装饰器通常用来装饰函数.或者类的方法# 被装饰后的函数,通常是在原有的函数基础上,会多出增加一点功能# 一般来说装饰器本身也是一个函数## def te ...

  7. python3 进一步了解装饰器 NLP第四条

    还是先来抄一段NLP第四条: 四,只有感官经验塑造出来的世界,没有绝对的真实世界   每个人运用自己的感觉器官把资料摄入(摄入过程),由于感官运用是主观地有选择性的,因此不能,亦不需要把所有资料捕获. ...

  8. 【python3】 函数 装饰器

    第一步 : 了解装饰器 装饰器模式,重点在于装饰,装饰的核心仍是被装饰的对象. 举一个栗子:我今天穿了一件短袖,但是突然一阵风,短袖没办法为我御寒,我想到的办法是将短袖变得更厚更长,但是改造之后,它就 ...

  9. Python3基础笔记--装饰器

    装饰器是十二分重要的高级函数. 参考博客:装饰器 所需前提知识: 1.作用域: LEGB 2.高阶函数 高阶函数是至少满足下列一个条件的函数: 1)接受一个或多个函数作为输入 2)输出一个函数 注意理 ...

随机推荐

  1. 常用jQuery知识

    什么是jQuery jQuery is a fast, small, and feature-rich JavaScript library. It makes things like HTML do ...

  2. hdu4403A very hard Aoshu problem 线段树

    //给一个长度为大于2小于15的字符串 //在当中间加'+'或'='使得其成为一个等式的方法的个数 //枚举等号位置.暴力搜索加号加的位置 #include<cstdio> #includ ...

  3. 算法笔记_232:提取拼音首字母(Java)

    目录 1 问题描述 2 解决方案   1 问题描述 在很多软件中,输入拼音的首写字母就可以快速定位到某个词条.比如,在铁路售票软件中,输入: “bj”就可以定位到“北京”.怎样在自己的软件中实现这个功 ...

  4. linux高精度struct timespec 和 struct timeval

    一.struct timespec 定义: typedef long time_t;#ifndef _TIMESPEC#define _TIMESPECstruct timespec {time_t ...

  5. C3P0连接池使用教程

     转载请注明原文地址:http://www.cnblogs.com/ygj0930/p/6405861.html  在项目中的应用见: https://github.com/ygj0930/Coupl ...

  6. 利用WatchService监听文件变化

    在实现配置中心的多种方案中,有基于JDK7+的WatchService方法,其在单机应用中还是挺有实践的意义的. 代码如下: package com.longge.mytest; import jav ...

  7. RHEL7 MariaDB测试

    MariaDB安装及启动: yum groupinstall mariadb 启动mariadb systemctl restart mariadb systemctl enable mariadb ...

  8. Spring Boot 在IDEA中debug时的hot deployment(热部署)

    因为Spring Boot的项目一般会打包成jar发布, 在开发阶段debug时, 不能像传统的web项目那样, 选择exploded resources进行debug, 也没有热更新按钮, 如果每次 ...

  9. NRF24L01无线模块的使用

    NRF2401芯片pin定义 NRF24L01模块pin定义 VCC 脚接电压范围为 1.9V~3.6V 之间, 不能在这个区间之外, 超过 3.6V 将会烧毁模块, 推荐电压 3.3V 左右 除电源 ...

  10. libev ev_init分析

    /* these may evaluate ev multiple times, and the other arguments at most once */ /* either use ev_in ...