Python之路,Day34 - Python基础-装饰器

1.装饰器

角色扮演:你是一家视频网站的后端开发工程师,你们网站有以下几个版块:

def home():

    print("---首页----")

def america():

    print("----欧美专区----")

def japan():

    print("----日韩专区----")

def henan():

    print("----河南专区----")

视频刚上线初期,为了吸引用户,你们采取了免费政策,所有视频免费观看,迅速吸引了一大批用户,免费一段时间后,每天巨大的带宽费用公司承受不了了,所以准备对比较受欢迎的几个版块收费,其中包括“欧美” 和 “河南”专区,你拿到这个需求后,想了想,想收费得先让其进行用户认证,认证通过后,再判定这个用户是否是VIP付费会员就可以了,是VIP就让看,不是VIP就不让看就行了呗。 你觉得这个需求很是简单,因为要对多个版块进行认证,那应该把认证功能提取出来单独写个模块,然后每个版块里调用 就可以了,与是你轻轻的就实现了下面的功能 。

#_*_coding:utf-8_*_

user_status = False     #用户登录了就把这个改成True

def login():

    _username = "alex" #假装这是DB里存的用户信息

    _password = "abc!23" #假装这是DB里存的用户信息

    global user_status

    if user_status == False:

        username = input("user:")

        password = input("pasword:")

        if username == _username and password == _password:

            print("welcome login....")

            user_status = True

        else:

            print("wrong username or password!")

    else:

        print("用户已登录,验证通过...")

def home():

    print("---首页----")

def america():

    login() #执行前加上验证

    print("----欧美专区----")

def japan():

    print("----日韩专区----")

def henan():

    login() #执行前加上验证

    print("----河南专区----")

home()

america()

henan()

此时你信心满满的把这个代码提交给你的TEAM LEADER审核,没成想,没过5分钟,代码就被打回来了, TEAM LEADER给你反馈是,我现在有很多模块需要加认证模块,你的代码虽然实现了功能,但是需要更改需要加认证的各个模块的代码,这直接违反了软件开发中的一个原则“开放-封闭”原则,简单来说,它规定已经实现的功能代码不允许被修改,但可以被扩展,即:

  • 封闭:已实现的功能代码块不应该被修改
  • 开放:对现有功能的扩展开放

这个原则你还是第一次听说,我擦,再次感受了自己这个野生程序员与正规军的差距,BUT ANYWAY,老大要求的这个怎么实现呢?如何在不改原有功能代码的情况下加上认证功能呢?你一时想不出思路,只好带着这个问题回家继续憋,媳妇不在家,去隔壁老王家串门了,你正好落的清静,一不小心就想到了解决方案,不改源代码可以呀。

你师从沙河金角大王时,记得他教过你,高阶函数,就是把一个函数当做一个参数传给另外一个函数,当时大王说,有一天,你会用到它的,没想到这时这个知识点突然从脑子 里蹦出来了,我只需要写个认证方法,每次调用 需要验证的功能 时,直接 把这个功能 的函数名当做一个参数 传给 我的验证模块不就行了么,哈哈,机智如我,如是你啪啪啪改写了之前的代码

#_*_coding:utf-8_*_

user_status = False #用户登录了就把这个改成True

def login(func): #把要执行的模块从这里传进来

    _username = "alex" #假装这是DB里存的用户信息

    _password = "abc!23" #假装这是DB里存的用户信息

    global user_status

    if user_status == False:

        username = input("user:")

        password = input("pasword:")

        if username == _username and password == _password:

            print("welcome login....")

            user_status = True

        else:

            print("wrong username or password!")

    if user_status == True:

        func() # 看这里看这里,只要验证通过了,就调用相应功能

def home():

    print("---首页----")

def america():

    #login() #执行前加上验证

    print("----欧美专区----")

def japan():

    print("----日韩专区----")

def henan():

    #login() #执行前加上验证

    print("----河南专区----")

home()

login(america) #需要验证就调用 login,把需要验证的功能 当做一个参数传给login

# home()

# america()

login(henan)

你很开心,终于实现了老板的要求,不改变原功能代码的前提下,给功能加上了验证,但是又犯了一个大忌,什么大忌?你改变了调用方式呀, 想一想,现在没每个需要认证的模块,都必须调用你的login()方法,并把自己的函数名传给你,人家之前可不是这么调用 的, 试想,如果 有100个模块需要认证,那这100个模块都得更改调用方式,这么多模块肯定不止是一个人写的,让每个人再去修改调用方式 才能加上认证,你会被骂死的。。。。

home()

login(america) #需要验证就调用 login,把需要验证的功能 当做一个参数传给login

# home()

# america()

login(henan)

你之所改变了调用方式,是因为用户每次调用时需要执行login(henan),类似的。其实稍一改就可以了呀

home()

america = login(america)  #你在这里相当于把america这个函数替换了

henan = login(henan)

这样你,其它人调用henan时,其实相当于调用了login(henan), 通过login里的验证后,就会自动调用henan功能。 

最终的代码如下:

#_*_coding:utf-8_*_

user_status = False #用户登录了就把这个改成True

def login(func): #把要执行的模块从这里传进来

    def inner(*args,**kwargs):#再定义一层函数

        _username = "alex" #假装这是DB里存的用户信息

        _password = "abc!23" #假装这是DB里存的用户信息

        global user_status

        if user_status == False:

            username = input("user:")

            password = input("pasword:")

            if username == _username and password == _password:

                print("welcome login....")

                user_status = True

            else:

                print("wrong username or password!")

        if user_status == True:

            func(*args,**kwargs) # 看这里看这里,只要验证通过了,就调用相应功能

    return inner #用户调用login时,只会返回inner的内存地址,下次再调用时加上()才会执行inner函数

def home():

    print("---首页----")

@login

def america():

    #login() #执行前加上验证

    print("----欧美专区----")

def japan():

    print("----日韩专区----")

@login

def henan(style):

    print("----河南专区----")

america()

猜你喜欢

转载自blog.csdn.net/sj349781478/article/details/82868409
今日推荐