装饰器

装饰器(最全解释)(转自传智播客就业班)
装饰器是程序开发中经常会⽤到的⼀个功能, ⽤好了装饰器, 开发效率如⻁
添翼, 所以这也是Python⾯试中必问的问题, 但对于好多初次接触这个知识
的⼈来讲, 这个功能有点绕, ⾃学时直接绕过去了, 然后⾯试问到了就挂
了 。
装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能同时又不改变其结构,作用是:
1、扩展一个类的功能。
2、动态增加功能,动态撤销。

问题引入:
看一段程序:

#装饰器
#f1() f2() f3() f4()是基本函数
def f1():
    pass

def f2():
    pass

def f3():
    pass

def f4():
    pass

#现需要调用这些函数
f1()
f2()
f3()
f4()

现提出新需求:为所有功能添加验证机制, 即: 执⾏函数前, 先进⾏验证。
1.首先可能会想到这样去改:(每次调用函数之前进行验证)

#f1() f2() f3() f4()是基本函数
def f1():
    pass

def f2():
    pass

def f3():
    pass

def f4():
    pass

#现需要调用这些函数
#验证函数()
f1()
#验证函数()
f2()
#验证函数()
f3()
#验证函数()
f4()

这种改法简直是太垃圾了。
2.看第二种改法:

#f1() f2() f3() f4()是基本函数
def f1():
    #验证函数1()
    #验证函数2()
    #验证函数3()
    pass

def f2():
    #验证函数1()
    #验证函数2()
    #验证函数3()
    pass

def f3():
    #验证函数1()
    #验证函数2()
    #验证函数3()
    pass

def f4():
    #验证函数1()
    #验证函数2()
    #验证函数3()
    pass

#现需要调用这些函数
f1()
f2()
f3()
f4()

这种改法修改的太多了,也垃圾

3.看第三张改法


def check_login():
    #验证函数1()
    #验证函数2()
    #验证函数3()
    pass

#f1() f2() f3() f4()是基本函数
def f1():
    check_login()
    pass

def f2():
    check_login()
    pass

def f3():
    check_login()
    pass

def f4():
    check_login()
    pass

#现需要调用这些函数
f1()
f2()
f3()
f4()

这种改法有进步,但是不符合开放封闭原则,虽然在这个原则是⽤的⾯向对象开发, 但是也适⽤于函数式编程, 简单来说, 它规定已经实现的功能代码不允许被修改,但可以被扩展, 即 :

  • 封闭: 已实现的功能代码块
  • 开放: 对扩展开发

如果将开放封闭原则应⽤在上述需求中, 那么就不允许在函数 f1 、 f2、 f3、f4的内部进⾏修改代码 。(运用闭包,引用等知识)

在这里插入图片描述
func指向f1和f2
这样算是实现了在不该f1()和f2()的提前下增加了验证功能,但是我们又发现一个问题:
原来我么是调用f1()和f2()函数,但现在却执行这两句:

innerFunc = w1(f1)    #w1()会返回inner,innerFunc 指向inner
innerFunc()
innerFunc = w1(f2)    #w1()会返回inner,innerFunc 指向inner
innerFunc()

这是有问题的。

为了满足上述条件现进行这样修改操作:

#装饰器
def w1(func):
    def inner():
        print("------验证权限-------")
        func()
    return inner

def f1():
    print("------1-------")

def f2():
    print("------2-------")


f1 = w1(f1)     #右边的f1指的是f1()函数的引用,而左边的f1是用来接收w1()函数的返回值的!!!!!!!!!!
f1()

f2 = w1(f2)
f2()

离成功又接近了一步!!!!!!
最后改成如下:

#装饰器
def w1(func):
    def inner():
        print("------验证权限-------")
        func()
    return inner

@w1    #语法糖   装饰方法
def f1():
    print("------1-------")
@w1    #语法糖   装饰方法
def f2():
    print("------2-------")

f1()
f2()

语法糖:具有特殊功能真甜真香,可以让原始的函数和调用方式都不用改变。
语法糖(Syntactic sugar):

  • 计算机语言中特殊的某种语法
  • 这种语法对语言的功能并没有影响
  • 对于程序员有更好的易用性
  • 能够增加程序的可读性

简而言之,语法糖就是程序语言中提供**[奇技淫巧]的一种手段和方式而已。 通过这类方式编写出来的代码,即好看又好用**,好似糖一般的语法。固美其名曰:语法糖。

再议装饰 多个装饰器



def makeBold(fn):
    print("------xxxxx-------")
    def wrapped():
        print("------1-------")
        return "<b>" + fn() +"</b>"
    return wrapped

def makeItalic(fn):
    print("------yyyyy-------")
    def wrapped():
        print("------2-------")
        return "<i>" + fn() +"</i>"
    return wrapped

@makeBold      #后装
@makeItalic    #先装
def test3():
    print("-----3------")
    return "Hello World!!!"


ret = test3()
print(ret)


结果:

------yyyyy-------
------xxxxx-------
------1-------
------2-------
-----3------
<b><i>Hello World!!!</i></b>

这个程序内部怎么运行的非常复杂,可以观看传智播客的就业班视频,讲解的非常详细。

对带有参数的函数进行装饰:

def w1(func):
    def inner():
        print("------验证权限-------")
        func()
    return inner

@w1    #语法糖
def f1(a,b):
    print("------1-------")
    print("------a = %d ,b = %d----------"%(a,b))

@w1    #语法糖
def f2(a,b):
    print("------2-------")
    print("------a = %d ,b = %d----------" % (a, b))

f1(11,22)
f2(33,44)

程序报错:

Traceback (most recent call last):
  File "E:/PythonProgram/test.py", line 36, in <module>
    f1(11,22)
TypeError: inner() takes 0 positional arguments but 2 were given

意思是inner()函数不要参数,却给了它两参数
这时应该这样改:

#装饰器
def w1(func):
    def inner(aa,bb):
        print("------验证权限-------")
        func(aa,bb)
    return inner

@w1    #语法糖
def f1(a,b):
    print("------1-------")
    print("------a = %d ,b = %d----------"%(a,b))

@w1    #语法糖
def f2(a,b):
    print("------2-------")
    print("------a = %d ,b = %d----------" % (a, b))

f1(11,22)
f2(33,44)

对带有返回值的函数进行装饰:


#装饰器
def w1(func):
    def inner(aa,bb):
        ret = func(aa,bb)
        return ret     #在这里需要添加return
    return inner

@w1    #语法糖
def f1(a,b):
    print("------1-------")
    print("------a = %d ,b = %d----------"%(a,b))
    return("How are you?")

ret = f1(11,22)
print(ret)

结果:

------1-------
------a = 11 ,b = 22----------
How are you?

带有参数的装饰器:在原有装饰器的基础上,设置外部变量,
可以装饰器进行选择


def w1(func):
    def inner():
        print("-------xxxxxx---------")
        func()
    return inner

@w1("hahahaha")     #带有参数的装饰器
def f1():
    print("------1-------")

f1()

报错:

Traceback (most recent call last):
  File "E:/PythonProgram/test.py", line 44, in <module>
    @w1("hahahaha")
TypeError: inner() takes 0 positional arguments but 1 was given

改法如下:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值