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 = funcarg指向函数的内存地址

第五步:执行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功能,并且调换了34的顺序

因此需要这样写:

def auth(func):
 
def inner():
   
print '验证功能'
   
func()
 
return inner
def 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()函数的返回值复制给f1
def f1():
 
print 'f1'
@auth_arg1  ==》会执行f1 = auth(f1),也就是inner()函数的返回值复制给f1
def f2(arg):
 
print 'f2,arg'
装饰器的实质就是在不修改f1函数体的情况下,执行f1函数之前,执行一个auth函数
有了装饰器,基础平台给500个函数增加认证功能,在不破坏开放封闭原则的情况下,只需要写一个auth函数和500个@auth,auth函数的inner子函数中实现认证功能,业务线不需要做任何修改,实现的功能就是f1函数执行之前进行身份验证,f1功能执行之后打印日志
当函数f2有一个参数的时候,需要另外写一个有一个参数的装饰器auth_arg1,在f2之前写上@auth_arg1即可
 
第5天该看06了