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)
复制代码

执行

 
posted @ 2021-01-24 21:57  uplee  阅读(52)  评论(0编辑  收藏  举报