3-20装饰器***

你是一家视频网站的后端开发工程师,你们网站有以下几个板块

def home():
    print("-----首页------")
    

def america():
    print("------欧美专区------")


def japan():
    print("-----日韩专区-----")


def henan():
    print("-----河南专区------")

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

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

def login():
    _username = 'alex' #假装这是DB里存的用户信息
    _password = 'abc123'#假装这是DB里存的用户信息
    global user_status
    if user_status == False:
        username = input("user:")
        password = input("password:")

        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()
    if user_status == True:
        print("------欧美专区------")


def japan():
    print("-----日韩专区-----")


def henan():
    login()
    if user_status == True:
         print("-----河南专区------")

henan()
america()

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

封闭:已实现的功能代码块不应该被修改

开放:对现有功能的扩展开放。

你想到了高阶函数,就是把一个函数当做一个参数传给另一个函数:

def login(func):
    _username = 'alex' #假装这是DB里存的用户信息
    _password = 'abc123'#假装这是DB里存的用户信息
    global user_status
    if user_status == False:
        username = input("user:")
        password = input("password:")

        if username == _username and password == _password:
            print("welcome login...")
            user_status = True
        else:
            print("wrong username or password!")
    else:
        print("用户已登录,验证通过...")
    if user_status == True:
        func() #只要验证通过了,就调用相应的功能



def home():
    print("-----首页------")

def america():
        print("------欧美专区------")

def japan():
    print("-----日韩专区-----")


def henan():
         print("-----河南专区------")

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

你的功能是实现了,但是你又犯了一个大忌,什么大忌?

你改变了调用方式啊,想一想,现在每个需要认证的模块,都必须调用你的login()方法,并把自己的函数名传给你,人家之前可不是这么调用的,试想,如果100个模块需要认证,那这100个模块都得更改调用方式,这么多模块肯定不止是一个人写的,让每个人再去修改调用方式才能加上认证,是不可能的。

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

home()
america = login(america)
henan = login(henan)

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

home()
america = login(america)
henan = login(henan)

#用户调用时依然写
america()

但是问题在于,还不等用户调用,你的

扫描二维码关注公众号,回复: 6967405 查看本文章
america = login(america)就会先自己把america执行了呀。。。。。你应该等用户调用的时候再执行呀

 

__author__ = 'apple'

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

def login(func):
    def inner():
        _username = 'alex' #假装这是DB里存的用户信息
        _password = 'abc123'#假装这是DB里存的用户信息
        global user_status
        if user_status == False:
            username = input("user:")
            password = input("password:")
    
            if username == _username and password == _password:
                print("welcome login...")
                user_status = True
            else:
                print("wrong username or password!")
        else:
            print("用户已登录,验证通过...")
        if user_status == True:
            func()#只要验证通过了,就调用相应的功能
    return inner



def home():
    print("-----首页------")

def america():
        print("------欧美专区------")

def japan():
    print("-----日韩专区-----")


def henan():
         print("-----河南专区------")

home()
america = login(america) #返回inner
henan = login(henan)

#用户调用时依然写
america() #执行inner

其实还可以更简单,只要在你要装饰的函数上面加上下面代码:

__author__ = 'apple'

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

def login(func):
    def inner():
        _username = 'alex' #假装这是DB里存的用户信息
        _password = 'abc123'#假装这是DB里存的用户信息
        global user_status
        if user_status == False:
            username = input("user:")
            password = input("password:")

            if username == _username and password == _password:
                print("welcome login...")
                user_status = True
            else:
                print("wrong username or password!")
        else:
            print("用户已登录,验证通过...")
        if user_status == True:
            func() #只要验证通过了,就调用相应的功能
    return inner



def home():
    print("-----首页------")

@login
def america():
        print("------欧美专区------")

def japan():
    print("-----日韩专区-----")

@login
def henan():
         print("-----河南专区------")

home()
#america = login(america) #返回inner
#henan = login(henan)

#用户调用时依然写
america() #执行inner

装饰带参数的函数:

__author__ = 'apple'

user_status = False #用户登陆了就把这个改成True
def login(func):
    def inner(*args,**kwargs):
        _username = 'alex' #假装这是DB里存的用户信息
        _password = 'abc123'#假装这是DB里存的用户信息
        global user_status
        if user_status == False:
            username = input("user:")
            password = input("password:")

            if username == _username and password == _password:
                print("welcome login...")
                user_status = True
            else:
                print("wrong username or password!")
        else:
            print("用户已登录,验证通过...")
        if user_status == True:
            func(*args,**kwargs) #只要验证通过了,就调用相应的功能
    return inner



def home():
    print("-----首页------")

@login
def america():
        print("------欧美专区------")

@login
def japan():
    print("-----日韩专区-----")

@login
def henan(style):
         print("-----河南专区------",style)

home()
#america = login(america) #返回inner
#henan = login(henan)

#用户调用时依然写
henan('tutu') #执行inner
japan()

后来,产品经理又提出了新的需求,要允许用户选择用qq\weibo\weixin认证

__author__ = 'apple'

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

def login(auth_type):
    def outer(func):
        def inner(*args,**kwargs):
            _username = 'alex' #假装这是DB里存的用户信息
            _password = 'abc123'#假装这是DB里存的用户信息
            global user_status
            if user_status == False:
                username = input("user:")
                password = input("password:")

                if username == _username and password == _password:
                    print("welcome login...")
                    user_status = True
                else:
                    print("wrong username or password!")
            else:
                print("用户已登录,验证通过...")
            if user_status == True:
                func(*args,**kwargs) #只要验证通过了,就调用相应的功能
        return inner
    return  outer



def home():
    print("-----首页------")


def america():
        print("------欧美专区------")


def japan():
    print("-----日韩专区-----")

@login('qq')
def henan(style):
         print("-----河南专区------",style)

home()

# funcxx = login('qq') #返回outer
# henan = funcxx(henan)
#
henan('tutu')
__author__ = 'apple'

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

def login(auth_type):
    def outer(func):
        def inner(*args,**kwargs):
            _username = 'alex' #假装这是DB里存的用户信息
            _password = 'abc123'#假装这是DB里存的用户信息
            global user_status
            if user_status == False:
                username = input("user:")
                password = input("password:")

                if username == _username and password == _password:
                    print("welcome login...")
                    user_status = True
                else:
                    print("wrong username or password!")
            else:
                print("用户已登录,验证通过...")
            if user_status == True:
                func(*args,**kwargs) #只要验证通过了,就调用相应的功能
        return inner
    return  outer



def home():
    print("-----首页------")


def america():
        print("------欧美专区------")


def japan():
    print("-----日韩专区-----")

@login('qq')  #henan = login('qq')(henan) 
def henan(style):
         print("-----河南专区------",style)

home()

# funcxx = login('qq') #返回outer
# henan = funcxx(henan)
#
henan('tutu')

猜你喜欢

转载自www.cnblogs.com/echo-kid-coding/p/11306406.html