http://www.cnblogs.com/wupeiqi/articles/4938499.html
python解释器执行顺序:从上到下
def foo(): -->将foo函数读入内存,但不执行函数体内容
print ‘abc‘ -->略过这行
foo -->表示foo函数,foo指向函数的内存地址
foo() -->表示执行foo函数,反过头取执行函数体内容print ‘abc‘
foo = lambda a : a + 1 -->foo指向另外一个函数的内存地址,这个函数实现的功能是a+1
foo() -->执行a+1这个函数的函数体
函数调用函数:
def f1(arg):
arg()
def func():
print "func"
f1(func)
python解释器从上往下执行
第一步:执行def f1(arg): 将函数写入内存,但是不执行函数体的内容arg()
第二步:执行def func():将函数写入内存,但是不执行函数体的内容print ‘func‘
第三步:执行f1(func)调用函数f1
第四步:执行def f1(arg): ,这时arg = func,arg指向函数的内存地址
第五步:执行arg(),arg() = func(),也就是执行func()函数
第六步:执行def func():
第七步:执行print ‘12‘
业务场景:
基础平台运维编写各种基础函数,提供各种API给产线,来查询数据库,各个机器的使用情况等功能
之前调用API没有做认证,现在想在500个函数中加入auth()函数做认证,基本的做法:
def auth(): xxxxxx
def f1(): auth() -->在函数体中增加auth()函数做认证 print "f1"def f2(): auth() -->在函数体中增加auth()函数做认证 print "f2"
但是由于开放封闭原则:
函数体不能被修改,只能修改配置文件或者main()函数来修改函数的执行顺序,或者增加新的函数来改变实现的功能
例如原来定义的函数执行顺序为1->2->3->4,现在修改为1->2->2.5->4->3,增加了一个2.5功能,并且调换了3和4的顺序
因此需要这样写:
def auth(func): def inner(): print ‘验证功能‘ func() return innerdef f1(): -->原函数 print ‘f1‘retval = auth(f1)retval()
第一步:执行def auth(func): ,将auth()函数加载到内存,但不执行函数体内容
第二步:执行def f1(): ,将f1()函数加载到内存,但不执行函数体内容
第三步:执行retval = auth(f1),调用auth()函数,同时传参f1
第四步:执行def auth(func): ,这时func == f1
第五步:执行def inner():,将auth()函数加载到内存,但是不执行inner()函数的函数体
第六步:执行return inner,这时retval == inner,retval也就等于整个inner()函数体
第七步:执行retval(),retval()==inner(),也就是执行inner()函数体,inner()函数体中有func(),而func()==f1,就执行了原来的函数f1
如果将retval = auth(f1),改写为f1= auth(f1) (第一个f1是新f1,第二个f1是老的f1函数)那么业务线的人就可以不用修改代码了
python提供了简单的写法,这种写法就是装饰器:
def auth(func): def inner(): print ‘认证功能‘ func()
print ‘打印日志‘ return inner
def auth_arg1(func): def inner(arg): print ‘认证功能‘ func(arg)
print ‘打印日志‘ return inner@auth ==》会执行f1 = auth(f1),也就是inner()函数的返回值复制给f1def f1(): print ‘f1‘
@auth_arg1 ==》会执行f1 = auth(f1),也就是inner()函数的返回值复制给f1def f2(arg): print ‘f2,arg‘
装饰器的实质就是在不修改f1函数体的情况下,执行f1函数之前,执行一个auth函数
有了装饰器,基础平台给500个函数增加认证功能,在不破坏开放封闭原则的情况下,只需要写一个auth函数和500个@auth,auth函数的inner子函数中实现认证功能,业务线不需要做任何修改,实现的功能就是f1函数执行之前进行身份验证,f1功能执行之后打印日志
当函数f2有一个参数的时候,需要另外写一个有一个参数的装饰器auth_arg1,在f2之前写上@auth_arg1即可
第5天该看06了