函数-函数进阶-装饰器
想象一下:
你是一家视频网站的后端开发工程师,你们网站有以下几个版本:
def home():
print("----首页----")
def america():
print("----欧美专区----")
def japan():
print("----日韩专区----")
def henan():
print("----河南专区----")
视频刚上线初期,为了吸引用户,你们采取了免费政策,所有视频免费观看,迅速吸引了一大批用户,免费一段时间后,每天巨大的带宽费用公司承受不了了,所以准
备对比较受欢迎的几个板块收费,其中包括“欧美”和“河南”专区,你拿到这个需求后,想了想,想收费得先让其用户认证,认证通过后,再判定这个用是否是vip付费会员就可以了,
是vip就让看,不是vip就不让看就行了呗。你觉得这个需求很是简单,因为要对多给版块进行认证,那应该把认证功能提取出来单独写个模块,然后每个版块里调用就可以了,与是你轻轻的就实现了下面的功能。
# -*-coding:utf-8-*-
user_status = Fales #用户登录了就把这个改成True
def login()
_username = "alex" #假装这是DB里存的用户信息
_password = "abc!23" #假装这是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() #执行前加上验证
print("----欧美专区----")
def japan():
print("----日韩专区----")
def henan():
login() #执行前加上验证
print("----河南专区----")
home()
america()
henan()
此时你信心满满的把这个代码提交给你的TEAM LEADER审核,没成想,没过5分钟,代码就呗打回来了,TEAM LEADER 给你反馈是,我现在有很多模块需要加认证
模块,你的代码虽然实现了功能,但是需要更改需要加认证的各个模块的代码,这直接违反了软件开发中的一个原则“开放-封闭”原则,简单来说,它规定已经实现的功能
代码不允许被修改,但可以被扩展,既:
。封闭:已实现的功能代码块不应该被修改
。开放:对现有功能的扩展开放
这个原则你还是第一次听说,我擦,再次感受了自己这个野生程序员与正规军的差距,BUT ANYWAY,老大要求的这个怎么实现呢?如何在不改原有功能代码的情况下
加上认证功能呢?你一时想不出思路,只好带着这个问题回家继续憋,媳妇不在家,去隔壁老王家串门了,你正好落的清净,一不小心就想到了解决方案,不改源代码可以呀。
你师从沙河金角大王时,记得他教过你,高阶函数,就是把一个函数当作一个参数传给另一个函数,当时大王说,有一天,你会用到它的,没想到这时这个知识点突然从脑子里蹦出来了,
我只需要写一个认证方法,每次掉哟个需要验证的功能时,直接把这个功能的函数名当作一个参数传给我的验证模块不就行了么,哈哈,机智如我,如是你啪啪啪改写了值卡的代码。
# -*-coding:utf-8-*-
user_status = Fales #用户登录了就把这个改成True
def login(func)
_username = "alex" #假装这是DB里存的用户信息
_password = "abc!23" #假装这是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:
func()
def home():
print("----首页----")
def america():
login() #执行前加上验证
print("----欧美专区----")
def japan():
print("----日韩专区----")
def henan():
login() #执行前加上验证
print("----河南专区----")
login(america)
login(henan)
你很开心,终于实现了老板的要求,不改变原功能代码的前提下,给功能加上了验证,此时,媳妇回来了,后面还跟着老王,你两家关系非常号,老王经常来串门,老王也是码农,你跟他分享了你写的代码,兴奋的等他看完,夸奖你NB,没想成,老王看后,并没有夸你,抱起你的儿子,笑笑说,你这个代码还是改改吧,要不然会被开除的,WHAT?会开出,明明实现了功能呀,老王讲,没错,你功能是实现了,但是你又犯了一个大忌,什么大忌?
你改变了调用方式呀,想一想,现在每个需要认证的模块,都必须调用你的login()方法,并把自己的函数名传给你,人家之前可不是这么调用的,试想,如有100给模块需要认证,那这100给模块都得更改调用方式,这么多模块肯定不止是一个人写的,让每个人再去修改调用方式才能加上认证,你会被骂死。。。
你觉得老王说的对,但问题是,如何即不改变原功能代码,又不改变原有调用的方式,还能加上认证?你苦思了一会,还是想不出,老王在都你的儿子玩,你说,老王呀,块给我点思路,实在想不出来,老王背对着你问,
老王:学过匿名函数没?
你:学过学过,就是lambda嘛
老王:那lambda 与正常函数的区别是什么?
你:你最直接的区别是,正常函数定义是需要写名字,但lambda不需要
老王:没错,那lambda 定好后,为了多次调用,可以也给它命给名?
你:可以呀,可以写成 plus =lambda x:x+1类似这样,以后再调用plus就可以了,但这样不就失去了lambda的意义了,明明人家匿名函数,你取名字还有什么作用呢?
老王:我不是要跟你他的医院,我想通过这个让你明白一个事实。
说着,老王拿起你儿子的画板,在上面写了一下一下代码:
def plus(n)
return n+1
plus2 = lambda x:x+1
老王:上面这两种写法是不是代表(同样的意思)
你:是的
老王:没啥,只想高速你,给函数赋值变量名就像def func_name 是一样的效果,如下面的plus(n)函数,你调用时可以用plus名,还可以再起个其他名字
calc = plus
calc(n)
你明白我想传达什么意思了么?
你:。。。。。。。。这。。。。。嗯。。。。不太。。。。明白。。。
老王:。。。。。这。。。。。。呵呵。。。。好吧。。。。那我在给你点一下,你之前写的下面这段调用 认证的代码
home()
login(america) #需要验证就调用login,需要验证功能 当做一个参数传给login
# home()
# america()
login(henan)
你之所改变了调用方式,是因为用户每次调用时需要执行login(henan),类似的。其实稍一改就可以了呀。
home()
america = login(america) # 你在这里相当于把america 这个函数替换了
henan = login(henan)
#那用户调用时依然写
america()
但问题在于,还没等用户调用,你的america = login(america)就会先自己把america执行了呀。。。 你应该等我用户调用的时候再执行
你看。。。
老王:哈哈,你说的没错,这样搞会出现这个问题?但你想想有没有解决办法呢?
你:我擦,你指的思路呀,大哥。。。我哪知道下一部怎么走。。。