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
2

难道为装饰器增加参数就这么的简单

  仔细的你可能已经发现了、我们在上面的代码里并没有用装饰器的语法糖衣、而是通过函数调用的方式来包装的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 12, in <module>
    @deprecated(‘add‘)
TypeError: deprecated() missing 1 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
2

总结:

  如果只能用一名话概括python我想对简洁的应该是“一切皆对象”了吧。

原文地址:https://www.cnblogs.com/JiangLe/p/9309566.html

时间: 2024-10-06 20:47:46

python3 如何给装饰器传递参数的相关文章

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

一.#1.执行outer函数,并且将其下面的函数名,当作参数 #2.将outer的返回值重新赋值给f1 = outer的返回值 #3.新f1 = inner #4.func = 原f1 1 #!/usr/bin/env python 2 def outer(func) : 3 def inner() : 4 print("hello") 5 print("hello") 6 print("hello") 7 r = func() 8 print(

python3学习之装饰器

#定义装饰器,outer参数是函数,返回也是函数 #作用:在函数执行前和执行后分别附加额外功能 def  outer(func):     def  inner(*args, **kwargs):         print("log")         func(*args, **kwargs)         print("Don't back")         # return "r"     return inner @outer de

Struts2Action请求转发以及参数 拦截器传递参数

@Result(name = "fail", type = "redirectAction", location = "gotologin.do?loginUrl=${loginUrl}&errorstr=${errorstr}") //Action请求转发以及参数 拦截器传递参数 ActionContext ac = invocation.getInvocationContext();ValueStack stack = ac.getV

装饰器(带参数)

如果明白装饰器的原理那么带参数的装饰器就很容易理解了 代码: def s1(func): def inner(a,b): #f1=inner(a,b) 接受2个参数,然后在把2个参数传递给func(a,b) print("hello") r =func(a,b) print("word") return r return inner @s1 def f1(a,b): print(a+b) f1(20,50) 现在有个问题如果装饰的函数有的参数是1个有的是2个怎么办?

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

案例: 为分析程序内哪些函数执行时间开销较大,我们需定义一个带timeout参数的装饰器 需求: 统计被装饰函数的运行时间 时间大于timeout时,将此次函数调用记录到log日志中 运行时可以修改timeout的值 如何解决这个问题? 定义一个装饰器,计算函数执行时间,并与timeout比较,当大于timeout时候,通过logging模块打印出日志信息 在包裹函数中添加一个函数,通过这个函数来修改timeout变量 在python3中用nonlocal来声明嵌套作用域中的变量引用,在pyth

装饰器的应用-装饰器带参数和不带参数

1 #!/usr/bin/env python 2 #encoding: utf-8 3 def start_info(): 4 print ('电视剧开头曲.......') 5 print ('开始唱歌.......') 6 def end_info(): 7 print ('电视剧结束曲.......') 8 9 def filter(start_info,end_info): #接收俩函数 10 def outer(main_fun): #接收装饰的函数 11 def app(*argv

python学习系列之python装饰器基础(6)---装饰器加参数

一.常规的装饰器,比如 @auth,执行2步操作: 1.执行auth函数,并传参func进来 2.获取返回值,并赋值给被装饰器的函数的函数名(如让fetch_server_list等于返回值) 二.而带参数的装饰器,比如 @auth(before,after),则执行3步操作: 1.执行auth(before,after)这个函数,得到返回值ret(假设返回值为ret) 2.创建装饰器,获取返回值,拼接为@ret 3.相当于@auth函数的2个步骤: 1)执行ret函数 2)将ret函数的返回值

Python3+selenium-unittest之装饰器(@classmethod)

1.setup():每个测试case运行前运行2.teardown():每个测试case运行完后执行3.setUpClass():必须使用@classmethod 装饰器,所有case运行前只运行一次4.tearDownClass():必须使用@classmethod装饰器,所有case运行完后只运行一次 import unittest import time class Test(unittest.TestCase): @classmethod def setUpClass(cls): pri

s14 第4天 关于python3.0编码 函数式编程 装饰器 列表生成式 生成器 内置方法

python3 编码默认为unicode,unicode和utf-8都是默认支持中文的. 如果要python3的编码改为utf-8,则或者在一开始就声明全局使用utf-8 #_*_coding:utf-8_*_ 或者将字符串单独声明: a = "中文".encode("utf-8") 函数式编程 函数式编程中的函数指代的是数学中的函数. 函数式编程输入如果确定,则输出一定是确定的.函数中并没有很多逻辑运算 python是一个面向对象的语言,只是一部分支持函数式编程.