装饰器 ==》一个提升逼格的玩意

  • 先来一简单实例,代码如下

def f1():
    print('123')

def f2(xxx):
    xxx()

f2(f1)    # f1没有加括号,代指函数整体,也就是说函数是可以被当作参数传递的!!
          # 函数只是定义,不被调用,解释器去解释的时候,内部代码是不会执行的!!
  • python中的装饰器decorator其实是一个高阶函数,它接受一个函数作为参数,并返回一个新的函数,从下往上编译,从上往下执行

def outer(func):
    def inner():
        print("before")
	func()
	print("after")
    return inner

@ + 函数名
功能:
    1、自动执行outer函数并且将其下面的函数名f1当作参数传递
    2、将outer函数的返回值,重复赋值给f1

@outer
def f1():
    print("F1")
  • 我们可以看到上面代码执行的是一个没有参数的函数,如果函数有参数,并且有多少个参数我们不知道,那该怎么办呢?

def log2(f):  
    def inner(*args, **kwargs):  # 这2个参数,会接受任意类型的参数  
        print("before")  
        r = f(*args,**kwargs)  
        print("after")  
        return r  
    return inner  
 
@log2  
def f2(name, age):  
    print('My name is %s, I am %s years old'%(name, age))  
  
f2('Eric', 24)  
#  输出  
# before  
# My name is Eric, I am 24 years old  
# after
  • 比方说一所中学有一个夏令营的活动,夏令营有各种活动,但是每个活动对学生的要求不一样,有的活动要求学生必须满18岁,有的活动要求学生必须考试分数及格(60),还有的活动必须要求学生2个都满足,每个活动都可以写成一个函数,如果这些要求条件我们都写成装饰器的话,就有点太冗余了,还好就是可以多重装饰,简单说就是一个函数可以有多个装饰器,代码如下

USER_INFO = {'age': 0, 'score': 0}  # 用户年龄及分数

def check_age(f):
    def inner(*args, **kwargs):
        if USER_INFO.get('age', None) >= 18:  # 检查年龄 是否满18
            r = f(*args, **kwargs)             # 年龄符合,调用方法
            return r
        else:
            print('你还未成年,一边待着去......')
    return inner

def check_score(f):
    def inner(*args, **kwargs):
        if USER_INFO.get('score', None) >= 60:  # 检查分数是否合格,60份合格
            r = f(*args, **kwargs)
            return r
        else:
            print('你考试不合格,继续努力......')
    return inner

# 2个装饰器修饰 会先执行判断年龄的装饰器,在执行判断分数的装饰器
@check_age
@check_score
def swimming():
    print('欢迎来游泳'.center(40, '*'))

@check_age
def basketball():
    print('欢迎来篮球队玩耍'.center(40, '*'))

@check_score
def football():
    print('欢迎来足球队飞'.center(40, '*'))
"""
  1.篮球不需要分数,但是要年龄满18岁
  2.足球不需要年龄,但要分数满60
  3.游泳急需要年龄满18 有需要分数满60
"""
def main():
    while True:
        imp = input('1.篮球, 2.足球, 3.游泳\n>>>')
        age = input('请输入你的年龄:')
        score = input('请输入你的分数:')
        USER_INFO['age'] = int(age)
        USER_INFO['score'] = int(score)
        if imp == '1':
            basketball()
        elif imp == '2':
            football()
        elif imp == '3':
            swimming()

if __name__ == '__main__':
    main()