前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >函数的衣服--装饰器

函数的衣服--装饰器

作者头像
数据山谷
发布2021-01-08 15:15:44
6300
发布2021-01-08 15:15:44
举报
文章被收录于专栏:数据山谷数据山谷
新品速递新品速递,双旦来袭,购物车还能放下么,不要忘记函数小朋友,在这个冬天也需要加衣呀~

Python装饰器本质上是一个Python函数,是一个特殊的闭包,它可以让其他函数在不需要做任何代码变动的前提下增加额外的功能,外层函数的返回值是内层函数,装饰器的返回值也是一个函数对象。

装饰器的作用顾名思义,就是装饰其他函数,为其他函数增加额外的功能,有了装饰器,我们就可以抽出大量与函数功能本身无关的代码复用。

▉应用场景:比方说我们有一个打印的功能

代码语言:javascript
复制
def print_now():
    print("it's cool")

▉这时,我想加一个需求,穿皮衣,如何加呢

代码语言:javascript
复制
def print_now():
    print("it's cool")
    print("Wear leather clothes")

ok,看起来很简单,但是如果我要同时给10个,100个函数都添加这个需求呢,并且还要都去打印执行,难道要一个个去添加,去修改原函数的代码吗?

ctrl+V也挺累,而且会造成大量重复的代码,为了减少这个工作量,我们可以重新定义一个函数,避免重复造轮子的现象。

代码语言:javascript
复制
import time
def use_decorate(func):
    def cop_time(*args,**kwargs):
        start = time.time()
        result = func(*args,**kwargs)
        stop = time.time()
        print(stop - start)
        return result
    return cop_time

@use_decorate
def index():
    print("from index")

index()

以上代码为例,有一个特殊的语法,让我们可以灵活地使用装饰函数。

代码语言:javascript
复制
特殊的语法: 语法糖--- @语法

@装饰器外层函数名
def 原始函数():
    pass

我们可以把原始函数看成裸露的肉体,装饰器就是为原始函数加上了外衣,这层外衣为原本的肉体增加了遮羞打扮的功能。

▉一个函数可以添加一个或多个装饰器

▉多个函数也可以使用同一个装饰器

▉对带参的函数进行修饰

代码语言:javascript
复制
def use_decorate(func):
    def cop_time(x,y):
        print("你看我跑了么")
        func(x,y)
    return cop_time

@use_decorate
def index(x,y):
    print(x,y)

index(1,2)

那么我们如何确定所需参数的数量呢,所以我们用到*args和**kwargs。

代码语言:javascript
复制
def use_decorate(func):
    def cop_time(*args,**kwargs):
        print("你看我跑了么")
        func(*args,**kwargs)
    return cop_time

@use_decorate
def index(x,y):
    print("我有两个参数是{}and{}".format(x,y))
@use_decorate
def temle(a,b,c):
    print("我有三个参数{}and{}and{}".format(a,b,c))
    
index(1,2)
temle(1,2,3)

由于语法糖@的限制,use_decorate函数只能有一个参数,并且该参数只用来接收被装饰对象的内存地址。

代码语言:javascript
复制
def use_decorate(func):
    def cop_time(*args,**kwargs):
        result = func(*args,**kwargs)
        return result
    return cop_time

@use_decorate
def index():
    print("from index")
index()

▉在这个例子中:

index的参数什么样子,cop_time的参数就应该什么样子。

index的返回值什么样子,cop_time的返回值就应该什么样子。

index的属性什么样子,cop_time的属性就应该什么样子。

接着,我们做一个小案例,现在有一个需求,增加一个装饰器,为julia添加一个认证的功能,在julia函数执行之前,先增加一个输入账号密码的步骤,认证成功在执行julia。

代码语言:javascript
复制
def clt(clother):
    def use_decorate(func):
        def cop_time(*args,**kwargs):
            name = input("请输入账号:").strip()
            pwd = input("请输入密码:").strip()
            if name == 'kayidao' and pwd == '123':
                result = func(*args,**kwargs)
                return result
                if clother == 'Nike':
                    print("欢迎光临Nike")
                elif clother == 'Puma':
                    print("欢迎光临Puma")
                elif clother == 'CV':
                    print("欢迎光临CV")
                else:
                    print("抱歉,你还不是会员")
            else:
                    print("请输入正确的账号或密码")
        return cop_time
    return use_decorate

@clt(clother='Nike')
def julia(x,y):
    print("这是julia会员")
    
@clt(clother='Puma')
def jack():
    print("这是jack会员")

@clt(clother='CV')
def bro():
    print("这是CV会员")

julia(1,2)
jack()
bro()

以调用julia为例,当调完clt时,得到的就是一个闭包函数use_decorate,接着use_decorate(julia),把julia这个函数放进来,得到的返回值再返回给julia。

▉总结:

使用装饰器: 需要为核心代码添加的新的功能 但是又不想修改核心代码的内容 就可以添加装饰器。

装饰器的格式:

def 外层函数名(形参):

def 内层函数名(*args, **kwargs):

要添加的内容

result = 原始功能的执行

return result

return 内层函数名

听说长得好看的人都拉到底点了看

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-12-29,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 数据山谷 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档