• 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)

    执行

  • 相关阅读:
    查看端口有没有被占用
    微信公众号2()
    How to insert a segment of noise to music file
    puppet practice
    Docker Commands
    LempelZiv algorithm realization
    The algorithm of entropy realization
    Java network programmingguessing game
    Deploy Openstack with RDO and Change VNC console to Spice
    puppet overview
  • 原文地址:https://www.cnblogs.com/zyxnhr/p/12317576.html
Copyright © 2020-2023  润新知