一、函数返回值
1.什么是函数返回值
顾名思义,函数返回值,就是一个函数的返回值,是一个函数名的情况
2.闭包
以计算多个数之和为例:
方法一:直接调用函数
def cacl_sum(*args):
all_sum = 0
for i in args:
all_sum += i
return all_sum
print cacl_sum(1,2,3,4,5)
运行效果:
15
方法二:采用闭包的方式
def lazy_sum(*args):
def cacl_sum():
all_sum = 0
for i in args:
all_sum += i
return all_sum
return cacl_sum
#调用lazy_sum(),得到返回值cacl_sum(是一个函数名)并赋给f
f = lazy_sum(1,2,3,4,5)
#调用 cacl_sum 函数并运行
print f()
注意: 当调用闭包 lazy_sum 时, 每次调用都返回一个新的函数。
f1 = lazy_sum(1,2,3,4,5)
f2 = lazy_sum(1,2,3,4,5)
print f1==f2
运行效果:
False
二、装饰器
1.什么是装饰器
- 装饰器的本质
器,可以理解为函数,装饰器实质上是用来装饰函数的,装饰器就是在原来功能基础上加上一些其他功能,即在程序执行前或者执行后加上需要的操作。
- 装饰器的功能
比如:权限的验证,日志记录, 函数运行时间统计, 执行函数前预备处理, 执行函数后清理
功能等。
2、装饰器的应用
<一>
背景:我们假设这么一个场景,某学生管理系统有不同的功能,我们想在每次执行一个功能的时候,都输出相同的欢迎语,我们当然可以分别在每个功能上添加这些欢迎的输出,但是当我们需要更改欢迎语的时候,是不是还得一一更改,那这样真的是太崩溃了,这个时候,装饰器就派上用场了
#装饰器
def addInfo(fun):
def wrapped():
print "欢迎使用XXX用户管理系统......"
fun()
return wrapped
# 装饰器的语法糖,
@addInfo
def login():
print "login...."
pass
@addInfo
def sign_in():
print "sign in......"
pass
@addInfo
def louout():
print "logout......"
pass
@addInfo
def Display_user_info():
print "Display_user_info......"
pass
login()
sign_in()
louout()
Display_user_info()
运行效果:
成功地为每一个功能模块都添加了欢迎信息,当我们需要对欢迎信息更改的时候,只需要更改该装饰器即可
欢迎使用XXX用户管理系统......
login....
欢迎使用XXX用户管理系统......
sign in......
欢迎使用XXX用户管理系统......
logout......
欢迎使用XXX用户管理系统......
Display_user_info......
那么,我么怎么理解装饰器的语法糖—-@addInfo呢???
以login()模块为例:
(1)当我们在调用login()的时候,先执行该模块的第一句@addInfo,实质就是将login()函数变为addInfo()函数的参数–(addInfo(login)),fun是形参,login是实参
(2)然后就执行addInfo()函数,该函数的返回值是一个函数名wrapped,
(3)所以接下来就执行函数wrapped()
(4)执行输出语句print后,顺序执行
(5)fun()就是在执行login()函数的内容,正如(1)所述fun是形参,login是实参
综上,调用login()实际上是指向函数wrapped
<二>函数计时器—–被装饰的函数有参数
import time #导入time模块
def timer(fun):
def wrapper(*args,**kwargs): #参数类型为可变参数和关键字参数
start_time = time.time()
time1 = time.ctime()
print "%s函数运行时间为%s" %(fun.__name__,time1)
fun(*args,**kwargs) #参数类型为可变参数和关键字参数
end_time = time.time()
time1 = end_time - start_time
print "%s函数运行了%ss" %(fun.__name__,time1)
return wrapper
@timer
def add(*a):
print "结果为:%d" %(sum(a))
add(1,2,4,7,8)
运行效果:
add函数运行时间为Mon Jan 15 16:22:02 2018
结果为:22
add函数运行了5.79357147217e-05s
<三>装饰器带参数
装饰器带参数就需要在该装饰器外面再包裹一层函数,用来传参
代码:
def addInfo1(a): #a是形参
def addInfo(fun):
def wrapped():
print "欢迎使用XXX用户管理系统%s页面......" %(a)
fun()
return wrapped
return addInfo
# 装饰器的语法糖
@addInfo1("login") #login是实参
def login():
print "login...."
pass
@addInfo1("sign in")
def sign_in():
print "sign in......"
pass
@addInfo1("logout")
def louout():
print "logout......"
pass
@addInfo1("Display_user_info")
def Display_user_info():
print "Display_user_info......"
pass
login()
sign_in()
louout()
Display_user_info()
运行效果:
欢迎使用XXX用户管理系统login页面......
login....
欢迎使用XXX用户管理系统sign in页面......
sign in......
欢迎使用XXX用户管理系统logout页面......
logout......
欢迎使用XXX用户管理系统Display_user_info页面......
Display_user_info......
这里的执行和<一>类似,不同的就是,在执行addInfo()函数之前,先执行了addInfo1()函数传递了装饰器的参数,返回了函数名addInfo,然后执行addInfo()函数,接下来就与<一>无异