[Python]装饰器

装饰器@作用:为函数新增功能,解决重复性的操作,使得代码简洁、更模块化。

例子:

1.无参

原功能函数和业务代码如下:

def checkLogin():
    print("登陆验证")


def fss():
    print("发说说")


def ftp():
    print("发图片")


a = 1
if a == 1:
    fss()
    checkLogin()
else:
    ftp()
    checkLogin()
#  代码冗余,需反复调用checkLogin()功能函数

使用装饰器修改如下: 

def checkLogin(func):
    # 这里是定义一个闭包
    def inner():
        print("登陆验证")
        func()
    return inner
#  这里返回inner()函数


def fss():
    print("发说说")
fss = checkLogin(fss)
'''相当于
    fss = def inner():
            print("登陆验证")
            func()
    即修改了fss函数
'''

def ftp():
    print("发图片")


a = 1
if a == 1:
    fss()
else:
    ftp()

 也使用@代替   fss = checkLogin(fss)    语句

def checkLogin(func):
    def inner():
        print("登陆验证")
        func()
    return inner


@checkLogin
#类似于将fss作为函数参数,传给checkLogin函数
def fss():
    print("发说说")
#  fss = checkLogin(fss)


def ftp():
    print("发图片")


a = 1
if a == 1:
    fss()
else:
    ftp()

以上两种方式输出相同,使用@(类似于一种语法糖)可以减少代码量。

注意:

装饰器的执行时间为立刻执行,写了@符号,则立刻执行。

可以使用多个装饰器,从上到下装饰,从下到上执行。

2.含参

原代码:

def zsq():
        print("-" * 30)


def pnum(num):
    print(num)


zsq()
pnum(123)

添加装饰器

def zsq(func):
    def inner(n):
        # 在装饰器里添加参数
        print("-" * 30)
        func(n)
    return inner


@zsq
def pnum(num):
    print(num)


pnum(123)

疑问:如果要传递两个、三个甚至n个参数怎么办?不停修改装饰器吗?

使用不定长参数!

def zsq(func):
    def inner(*args, **kwargs):
        # 在装饰器里添加不定长参数
        print("-" * 30)
        func(*args, **kwargs)
    #     元组拆包; 字典拆包
    return inner


@zsq
def pnum(num, num2, num3):
    print(num, num2, num3)


@zsq
def pnum2(num):
    print(num)


pnum(123, 234, num3=666)
pnum2(1234)

输出结果:

 为什么pnum2可以只传一个参数?解释如下:

def zsq(func):
    def inner(*args, **kwargs):
        print("-" * 30)
        print(args, kwargs)
    return inner


@zsq
def pnum(num, num2):
    print(num, num2)


pnum(123, 234)

从输出结构可以看到前两个以元组形式传入,而字典为空。(不定长可以为0)

传递一个参数时,则代表元组中只有一个元素,且字典也为空。

想要字典不为空,则通过关键字参数形式调用:

def zsq(func):
    def inner(*args, **kwargs):
        # 在装饰器里添加不定长参数
        print("-" * 30)
        print(args, kwargs)
        func(*args, **kwargs)
    #     元组拆包; 字典拆包
    return inner


@zsq
def pnum(num, num2, num3):
    print(num, num2, num3)


#  关键字参数调用形式 num3 = 666
pnum(123, 234, num3 = 666)

代码运行结果如下:

注意:

对有返回值的函数进行装饰时,无论什么场景,要保证函数返回值一致。

调用不同装饰器

def zsq1(func):
    def inner():
        print("-" * 30)
        func()
    return inner


def zsq2(func):
    def inner():
        print("+" * 30)
        func()
    return inner


def zsq1(func):
    def inner():
        print("-" * 30)
        func()
    return inner


def zsq3(func):
    def inner():
        print("*" * 30)
        func()
    return inner


@zsq1
def f1():
    print("不同分割线的装饰器")

上述代码冗余

利用装饰器修改如下:

def getzsq(char):
    def zsq1(func):
        def inner():
            print(char * 30)
            func()
        return inner
    return zsq1


@getzsq("-")  #  f1 = zsq(f1)
def f1():
    print("不同分割线的装饰器")

带有参数的装饰器:

1. 通过@装饰器(参数)的方式,调用这个函数,并传递参数;并把返回值,再次当作装饰器进行使用。

2. 先计算@后面的内容,把这个内容当作是装饰器。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值