• 030. Python装饰器



    一  装饰器

    1.1 装饰器介绍

    扩展函数新功能的@
    定义:替换旧函数,返回新函数,在不改变原有代码的前提下,为该函数扩展新功能;
    语法:@ (语法糖)

    1.2 装饰器的原型

    复制代码
    def show(func):
            def showtime():
                    print ("演出开始")
                    func()
                    print ("演出结束")
            return showtime
    def func():
            print ("正在演出")
    res = show(func)
    res()
    复制代码

    执行

    [root@node10 python]# python3 test.py
    演出开始
    正在演出
    演出结束

    res换成func

    复制代码
    def show(func):
            def showtime():
                    print ("演出开始")
                    func()
                    print ("演出结束")
            return showtime
    def func():
            print ("正在演出")
    func = show(func)   # func = showtime  <==> func() 就是showtime() 一样的
    func()
    print(func)
    复制代码

    执行

    [root@node10 python]# python3 test.py
    演出开始
    正在演出
    演出结束
    <function show.<locals>.showtime at 0x7f3bc56a0158>

    1.3 装饰器语法@

    复制代码
    def show(func):
            def showtime():
                    print ("演出开始")
                    func()
                    print ("演出结束")
            return showtime
    @show      #func = show(func)
    def func():
            print ("正在演出")
    func()
    复制代码

    执行

    [root@node10 python]# python3 test.py
    演出开始
    正在演出
    演出结束

    方向:从下到上,把func当成一个参数给装饰器showt,返回的新函数覆盖旧函数func,func在调用时,相当于调用showtime(),只不过@自动帮助你实现了这一步,func = show(func)直接调用即可.

    1.4 装饰器的嵌套

    复制代码
    def show1(func):
            def showtime():
                    print ("演出开始")
                    func()
                    print ("演出结束")
            return showtime
    def show2(func):
            def showtime():
                    print ("准备演出")
                    func()
                    print ("退出演出")
            return showtime
    @show1
    @show2
    def func():
            print ("正在演出")
    func()
    复制代码

    执行

    演出开始
    准备演出
    正在演出
    退出演出
    演出结束

    执行过程

    1 自下而上执行,先执行@show2,即达到func = showtime(func),即此时func是

     print ("准备演出")
     print ("正在演出")
     print ("退出演出")

    2 在执行@show1,此时在执行show1的func = showtime(func)即此时func是

     print ("演出开始")
     print ("准备演出")
     print ("正在演出")
     print ("退出演出")
     print ("演出结束")

    3 得到最终结果

    复制代码
    [root@node10 python]# python3 test.py
    演出开始
    准备演出
    正在演出
    退出演出
    演出结束
    复制代码

    1.5 带有参数的装饰器

    如果原函数带有参数,  那么返回的新函数也要带有参数,(参数一一对应)

    复制代码
    def show(func):
            def showtime(who,where):
                    print ("准备演出")
                    func(who,where)
                    print ("退出演出")
            return showtime
    @show
    def func(who,where):
            print ("{}正在{}演出".format(who,where))
    func("张靓颖","鸟巢")
    复制代码

    执行

    [root@node10 python]# python3 test.py
    准备演出
    张靓颖正在鸟巢演出
    退出演出

    1.6 带有参数返回值的装饰器

    元祖和字典的参数用法,* 和 ** 的魔术用法  *[1,2,3] **{'a':1,'b':2} 把容器里面的数据,一个一个拿出来当成参数赋给调用处的func

    def func(*args):
            print(args)
    func(1,2,3,4,5)

    执行

    [root@node10 python]# python3 test.py
    (1, 2, 3, 4, 5)

    字典

    def func(*args,**kwargs):
            print(args)
            print(kwargs)
    func(1,2,3,4,5,a = 5,b = 6)

    执行

    [root@node10 python]# python3 test.py
    (1, 2, 3, 4, 5)
    {'a': 5, 'b': 6}

    实例

    复制代码
    #带有参数的装饰器
    def func_arg(arg):
            def funcAll(funcName):
                    def func_in(*args,**kwargs):
                            if arg=="2":#根据装饰的参数不同,可以进行不同的处理
                                    ret=funcName(*args,**kwargs)
                                    ret=funcName(*args,**kwargs)
                            else:
                                    ret=funcName(*args,**kwargs)
                            print("arg is %s"%arg)
                            return ret
                    return func_in
            return funcAll
    #运行分析:
    #1 先执行func_arg("hello")函数,这个函数return的结果是func这个函数的引用
    #2 @func_arg("hello")----->@funcAll
    #3 使用@func对testArg()进行装饰
    
    
    @func_arg("hello")
    def testArg():
            print("---带有参数的装饰器---")
    
    @func_arg("2")
    def testArg2():
            print("---带有参数的装饰器---")
    testArg()
    testArg2()
    复制代码

    执行

    复制代码
    [root@node10 python]# python3 test.py
    ---带有参数的装饰器---
    arg is hello
    ---带有参数的装饰器---
    ---带有参数的装饰器---
    arg is 2
    复制代码
    复制代码
    def func(*args,**kwargs):
            dictvar = {"xunyu":"荀彧","zhugeliang":"诸葛亮","zhangzhao":"张昭"}
            lst = {a:b for a,b in kwargs.items() if a in dictvar}
            return lst
    res = func("魏蜀吴","三国",xunyu="曹操",zhugeliang="刘备",zhangzhao="孙权")
    print (res)
    复制代码

    执行

    [root@node10 python]# python3 test.py
    {'xunyu': '曹操', 'zhugeliang': '刘备', 'zhangzhao': '孙权'}

    替换

    复制代码
    def func(*args,**kwargs):
            dictvar = {"xunyu":"荀彧","zhugeliang":"诸葛亮","zhangzhao":"张昭"}
            lst = {dictvar[a]:b for a,b in kwargs.items() if a in dictvar}
            return lst
    res = func("魏蜀吴","三国",xunyu="曹操",zhugeliang="刘备",zhangzhao="孙权")
    print (res)
    复制代码

    执行

    [root@node10 python]# python3 test.py
    {'荀彧': '曹操', '诸葛亮': '刘备', '张昭': '孙权'}

    使用字符串

    复制代码
    def func(*args,**kwargs):
            dictvar = {"xunyu":"荀彧","zhugeliang":"诸葛亮","zhangzhao":"张昭"}
            #lst = {dictvar[a]:b for a,b in kwargs.items() if a in dictvar}
            lst = [dictvar[a]+"主公是"+b  for a,b in kwargs.items() if a in dictvar]
            return lst
    res = func("魏蜀吴","三国",xunyu="曹操",zhugeliang="刘备",zhangzhao="孙权")
    print (res)
    复制代码

    执行

    [root@node10 python]# python3 test.py
    ['荀彧主公是曹操', '诸葛亮主公是刘备', '张昭主公是孙权']

    1.7 装饰器进行扩展

    复制代码
    def chuzheng(func):
          # 函数的定义处,*args,**kwargs 是收集参数 def chuzhengtime(*args,**kwargs): print ("出谋划策") lst = func(*args,**kwargs) print ("烽火连天") return lst return chuzhengtime def func(*args,**kwargs): print (args) dictvar = {"xunyu":"荀彧","zhugeliang":"诸葛亮","zhangzhao":"张昭"} #lst = {dictvar[a]:b for a,b in kwargs.items() if a in dictvar} lst = [dictvar[a]+"主公是"+b for a,b in kwargs.items() if a in dictvar] return lst res = func("魏蜀吴","三国",xunyu="曹操",zhugeliang="刘备",zhangzhao="孙权") print (res)
    复制代码

    执行

    [root@node10 python]# python3 test.py
    ('魏蜀吴', '三国')
    ['荀彧主公是曹操', '诸葛亮主公是刘备', '张昭主公是孙权']

    使用装饰器

    复制代码
    def chuzheng(func):
            def chuzhengtime(*args,**kwargs):
                    print ("出谋划策")
                    lst = func(*args,**kwargs)
                    print ("烽火连天")
                    return lst
            return chuzhengtime
    @chuzheng
    def func(*args,**kwargs):
            print (args)
            dictvar = {"xunyu":"荀彧","zhugeliang":"诸葛亮","zhangzhao":"张昭"}
            #lst = {dictvar[a]:b for a,b in kwargs.items() if a in dictvar}
            lst = [dictvar[a]+"主公是"+b  for a,b in kwargs.items() if a in dictvar]
            return lst
    res = func("魏蜀吴","三国",xunyu="曹操",zhugeliang="刘备",zhangzhao="孙权")
    print (res)
    复制代码

    执行

    [root@node10 python]# python3 test.py
    出谋划策
    ('魏蜀吴', '三国')
    烽火连天
    ['荀彧主公是曹操', '诸葛亮主公是刘备', '张昭主公是孙权']

    二 property 装饰器

    2.1 介绍

    • 功能:可以把类中的方法变成属性
    • 作用:控制该属性的 获取, 设置 ,删除 的操作
    1. @property 用来获取值
    2. @自定义名.setter 用来设置值
    3. @自定义名.deleter 用来删除值
    复制代码
    class MyClass():
            def __init__(self,name):
                    self.name = name
            def username(self):
                    return self.name
    obj = MyClass("John")
    res = obj.username()
    print (res)
    复制代码

    执行

    [root@node10 python]# python3 test.py
    John

    2.2 使用property

    复制代码
    class MyClass():
            def __init__(self,name):
                    self.name = name
            @property
            def username(self):
                    return self.name
    obj = MyClass("John")
    #获取username属性 print (obj.username)
    复制代码

    执行

    [root@node10 python]# python3 test.py
    John

    2.3 设置和删除

    复制代码
    class MyClass():
            def __init__(self,name):
                    self.name = name
            @property
            def username(self):
                    return self.name
            @username.setter
            def username(self,val):
                    self.name = val
            @username.deleter
            def username(self):
                    del self.name
    obj = MyClass("John")
    print (obj.username)
    #设置username属性
    obj.username = "wellian"
    print(obj.username)
    
    #删除username属性
    del obj.username    #这个可以删除,但是不能执行打印,会报错
    #print(obj.username)
    复制代码

    执行

    [root@node10 python]# python3 test.py
    John
    wellian

    打印删除的属性

    复制代码
    class MyClass():
            def __init__(self,name):
                    self.name = name
            @property
            def username(self):
                    return self.name
            @username.setter
            def username(self,val):
                    self.name = val
            @username.deleter
            def username(self):
                    del self.name
    obj = MyClass("John")
    print (obj.username)
    #设置username属性
    obj.username = "wellian"
    print(obj.username)
    
    #删除username属性
    del obj.username
    print(obj.username)
    复制代码

    执行

    2.4 控制

    可以使用pass占位,则就取不到username的值

    复制代码
    class MyClass():
            def __init__(self,name):
                    self.name = name
            @property
            def username(self):
                    #return self.name
                    pass
            @username.setter
            def username(self,val):
                    self.name = val
            @username.deleter
            def username(self):
                    del self.name
    obj = MyClass("John")
    print (obj.username)
    #设置username属性
    #obj.username = "wellian"
    #print(obj.username)
    
    #删除username属性
    #del obj.username
    #print(obj.username)
    复制代码

    执行,就取不到值

    设置使用控制

    复制代码
    class MyClass():
            def __init__(self,name):
                    self.name = name
            @property
            def username(self):
                    return self.name
                    #pass
            @username.setter
            def username(self,val):
                    #self.name = val
                    pass
            @username.deleter
            def username(self):
                    del self.name
    obj = MyClass("John")
    #print (obj.username)
    #设置username属性
    obj.username = "wellian"
    print(obj.username)
    
    #删除username属性
    #del obj.username
    #print(obj.username)
    复制代码

    执行,发现设置并没有成功

    同样删除也进行控制

    复制代码
    class MyClass():
            def __init__(self,name):
                    self.name = name
            @property
            def username(self):
                    return self.name
                    #pass
            @username.setter
            def username(self,val):
                    #self.name = val
                    pass
            @username.deleter
            def username(self):
                    #del self.name
                    pass
    obj = MyClass("John")
    #print (obj.username)
    #设置username属性
    #obj.username = "wellian"
    #print(obj.username)
    
    #删除username属性
    del obj.username
    print(obj.username)
    复制代码

    执行,仍然有值

     2.5 第二种写法

    复制代码
    class MyClass():
            def __init__(self,name):
                    self.name = name
            def getusername(self):
                    return self.name
                    #pass
            def setusername(self,val):
                    self.name = val
                    #pass
            def delusername(self):
                    del self.name
                    #pass
        #按照顺序传参,获取,设置, 删除
         username = property(getusername,setusername,delusername) obj = MyClass("John") print (obj.username) #设置username属性 obj.username = "wellian" print(obj.username) #删除username属性 del obj.username print(obj.username)
    复制代码

    执行

    推荐使用,当在定义一个可以直接定义

    复制代码
    class MyClass():
            def __init__(self,name):
                    self.name = name
            def getusername(self):
                    return self.name
                    #pass
            def setusername(self,val):
                    self.name = val
                    #pass
            def delusername(self):
                    del self.name
                    #pass
            username = property(getusername,setusername,delusername)
            address = property(getusername,setusername,delusername)
    obj = MyClass("John")
    print (obj.username)
    #设置username属性
    #obj.username = "wellian"
    #print(obj.username)
    
    #删除username属性
    #del obj.username
    #print(obj.username)
    print (obj.address)
    复制代码

    执行

     
    学习记录,小白一枚
  • 相关阅读:
    js篇之对象数据属性与存取器属性
    使用ts-loader与webpack编译typescripts出现Module build failed: TypeError: Cannot read property 'afterCompile' of undefined
    js对象深拷贝
    前端工程化之webpack中配置babel-loader(四)
    前端工程化-webpack篇之babel-polyfill与babel-runtime(三)
    process.cwd()与__dirname的区别
    jade(pug)学习和使用
    [bzoj4033][HAOI2015]树上染色_树形dp
    [bzoj2657][Zjoi2012]旅游 journey_ 对偶图_树形dp
    [bzoj2097][Usaco2010 Dec]Exercise 奶牛健美操_贪心_树形dp_二分
  • 原文地址:https://www.cnblogs.com/wangsirde0428/p/14322581.html
Copyright © 2020-2023  润新知