python核心--装饰器

装饰器

1.什么是装饰器

装饰器本质上是一个Python函数,它可以让其他函数在不需要做任何代码变动的前提下增加额外功能,装饰器的返回值也是一个函数对象。它经常用于有切面需求的场景,比如:插入日志、性能测试、事务处理、缓存、权限校验等场景。装饰器是解决这类问题的绝佳设计,有了装饰器,我们就可以抽离出大量与函数功能本身无关的雷同代码并继续重用。

2.需要装饰器的需求(原因)

想象一下可以假如公司有部门有两个函数。

def in_office():   # 进入办公室
    print("已经进入办公室")
def in_hall():  # 进入大厅
    print("已经进入大厅")  # bug here
in_office()
in_hall()

  输出结果:

  已经进入办公室     已经进入大厅

随着公司的发展,办公室不是谁想进就可以,需要某些权限的人才能进,这时候就需要一个验证功能。

一个员工是这样改的:

def in_office():   # 进入办公室
    print('进行验证')
    print("已经进入办公室")
def in_hall():  # 进入大厅
    print('进行验证')
    print("已经进入大厅")  # bug here
in_office()
in_hall()

结果他一周就被开除了。大家发现了,这样很繁琐是不是?公司老板发出邀请,谁要是能解决这个问题,工资涨1000.不一会就有一个人站了出来,说“我能做,用个装饰器就行了”

def check(func):
    def inner(name):
        if name < 5:   #这里表示小于5的权限可以进入,大的没有权限
            print('可以进入')
            return func
        else:
            print('权限不足')
    return inner
@check
def in_office():   # 进入办公室
    print('进行验证')
    print("已经进入办公室")
def in_hall():  # 进入大厅
    print('进行验证')
    print("已经进入大厅")  # bug here
in_office(8)     

  结果输出:

没有权限

  解释:

如果是第一次见装饰器的话,那这段代码可能会看着有点迷糊。我用我们之前学到的闭包来解释一下,重新把这个代码写一遍。

看到这个用闭包知识解释的装饰器,大家是不是就比较明白了。我的理解是装饰器就是一个闭包加一个函数。

3.装饰器时间问题

def check(func):
    print('已经装饰了')
    def inner(name):
        if name < 5:
            print('可以进入')
            return func
        else:
            print('权限不足')
    return inner
@check      #只要python解释器执行到这,就会进行自动的装饰 只是在调用的时候才把装饰器产生的
def in_office():   # 进入办公室                          # 效果发挥出来
    print('进行验证')
    print("已经进入办公室")

  结果输出:

  已经装饰了

4.装饰器的顺序问题

def makeBold(fn):
    def wrapped():
        return "<b>"+fn()+"</b>"   # 给函数输出左右加b
    return wrapped
def    makeItalic(fn):
    def    wrapped():
        return "<i>"+fn()+"</i>"    # 给函数输出左右加i
    return wrapped
@makeBold
@makeItalic
def test3():
    return "hello  world-3"
print(test3())

  解释:

按照正常理解,先执行了加b装饰器,又执行了加i装饰器,结果应该是<i><b>hello world-3</b></i>

但是结果是:<b><i>hello world-3</i></b>。对!装饰器的顺序是谁挨近,谁先执行。

5.装饰器参数问题

在参数这边我可能讲得不是太清楚,所以在这里分类一下装饰器的参数问题。

参数的分类大致有这么几种:

                     函数有参                                        函数有参

装饰器无参                                     装饰器有参

                     函数无参                                        函数无参

刚才那个我展示的是函数有参、装饰器无参,是这几个中等的。我这里分类是为了区分哪个是函数参、哪个是装饰器参。下面我就写一个特例:函数有不定长参,但装饰器无参的。

def debug(func):
    def wrapper(*args, **kwargs):  # 指定不定长参数
        print("[DEBUG]: enter {}()".format(func.__name__))
        return func(*args, **kwargs)    # 这里和上面相搭配
    return wrapper  # 返回

@debug   # 功能是在执行函数前,输出该函数的函数名
def say(something):
    print("hello {}!".format(something))
say('小米')

   解释:

  say()函数的参数可以是一个,也可以是两个或者一个列表都行。

6.函数的应用

前几天我在看电视《我爱发明》的时候,看到有人发明了一个自动筛选果子大小的机器,于是我灵机一动,可以拿这个作为装饰器的例子啊!

# 装饰器例子
def split(func):
    list2, list3 = [], []  # list2放小果子  list3放大果子
    def inner(apples):
        for apple in apples:
            if apple >5:
                list3.append(apple)
            else:
                list2.append(apple)
        # print(list2,list3)
        return func
    return inner
@split
def collect(args):
    for s in args:
        print(s)

list1 = [1,5,8,7,3,4,9,1,8,2,6,7,2,5,3,8,4]
collect(list1)

  结果输出:

  [1, 5, 3, 4, 1, 2, 2, 5, 3, 4] [8, 7, 9, 8, 6, 7, 8]

  解释:

这个装饰器,实现了一个果子大小分类的这么一个作用。在我理解,装饰器就是添加功能的。虽然功能很简单,但是应该解释了那个道理了。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值