本文主要学习内容有
函数知识的补充
装饰器(无参、有参、非固定参数、有返回值)
一、函数知识的补充
1、使用函数的好处
可以进行模块化设计,如果不使用函数的话,在完成某些功能或者某些项目时,所有的功能都堆积在一起了,那么久容易造成:
① 体系结构不清晰,可读性差
② 可扩展性差
③ 程序冗长
2、定义函数
def fun(args)
'''文档描述,函数的功能、参数等信息'''
print("in the fun")#函数体
return #返回值
3、定义函数的形式
def foo():
'''无参函数'''
foo()
def bar(x,y):
'''有参函数'''
bar(1,2)
def func():
'''空函数'''
pass
4、函数的调用
函数的调用有:语句形式、表达式形式、作为另外一个函数的参数
#语句形式
def foo():
print('in the foo')
foo()
#表达式形式
def my_max(x,y):
if x > y:
return x
else:return y
res = my_max(1,2)
print(res)
res2 = 10*my_max(1,2)#表达式形式
print("res2:",res2)
#作为另外一个函数的参数
res3 = my_max(1,my_max(2,3))
print("res3",res3)
5、函数的返回值形式
不返回内容、返回1个、返回多个
#不返回
def foo():
pass
res = foo()
print(res)
#返回一个
def foo1():
return 1
res1 = foo1()
print(res1)
#返回多个
def foo3():
return 1,'s',[1,2,3]
res3 = foo3()
print(res3)
6、函数的参数
定义形参的时候不用定义参数的类型,这就是参数的动态性。
从实参角度讲:
针对同一个形参,我们要么按照位置传参、要么按照关键字传参。
从形参角度讲:
站在形参角度讲,位置参数(特性:必传)、默认参数、可变长参数(*args,**kwargs)
*args 等同于按位置方式传参;**kwargs等同于按关键字方式传参
7、高阶函数
高阶函数的定义:
① 函数接收的参数是一个函数名
② 函数的返回值是一个函数名
满足以上任意一个条件,都可称之为高阶函数
def foo():
print('我的函数名将要作为参数传给高阶函数')
def gaojie1(func):
print('我就是高阶函数1,接收一个函数名为参数%s'%func)
func()
def gaojie2(func):
print('我是高阶函数2,将一个函数名返回给函数%s'%func)
return func
res1 = gaojie1(foo)
res2 = gaojie2(foo)
高阶函数的应用1:
#高阶函数的应用1:把函数当做参数传给高阶函数
import time
def foo():
print('from the foo')
def timmer(func):
start_time=time.time()
func()
stop_time=time.time()
print('函数%s 运行时间是%s' %(func,stop_time-start_time))
timmer(foo)
#总结:我们确实为函数foo增加了foo运行时间的功能,但是foo原来的执行方式是foo(),现在我们需要调用高阶函数timmer(foo),改变了函数的调用方式
高阶函数的应用2:
#高阶函数应用2:把函数名当做参数传给高阶函数,高阶函数直接返回函数名
import time
def foo():
print('from the foo')
def timmer(func):
start_time=time.time()
return func
stop_time=time.time()
print('函数%s 运行时间是%s' %(func,stop_time-start_time))
foo=timmer(foo)
foo()
#总结:我们确实没有改变foo的调用方式,但是我们也没有为foo增加任何新功能
高阶函数的总结:
① 函数接收的参数时一个函数名
作用:在不修改函数源代码的前提下,为函数添加新功能
不足:会改变函数的调用方式
② 函数的返回值是一个函数名
作用:不修改函数的调用方式
不足:不能添加新功能
8、嵌套函数
def one(name):
print('一级 %s' %name)
def two():
print('二级')
def two1():
print('三级')
two1()
two()
one('xiaoling')
9、闭包
'''
闭包:在一个作用域里放入定义变量,相当于打了一个包
'''
def one(name):
def two():
print('我是一级 [%s]' %name)
def two1():
print('我上级的上级 [%s]' %name)
two1()
two()
one('xiaoling')
二、装饰器
什么是装饰器?就是函数,为他人装饰(其他函数),就是为其他函数增加功能。
装饰器遵循的原则:
1、不修改被装饰函数的源代码(开放封闭原则)
2、为被装饰的函数装新增功能后,不改变原函数的调用方式
1.1、无参装饰器:
import time,functools
#无参数
def timer(func):
def wrapper():
start_time = time.time()
func() #运行最原始的index
stop_time = time.time()
print("运行时间%s"%(stop_time-start_time))
return wrapper
@timer #index = timer(index)
def index():
print('in the index:')
index()
1.2、被装饰的函数需要传参
import time,functools
#index有参数
def timer(func):
def wrapper(msg):
start_time = time.time()
func(msg) #运行最原始的index
stop_time = time.time()
print("运行时间%s"%(stop_time-start_time))
return wrapper
@timer #index = timer(index)
def index(msg): #该参数实际是传到wrapper函数了,接受到该参数后给func使用。
print('in the index:',msg)
index('hello')
1.3、被装饰的函数需要传多个参数
def timer(func):
def warpper(*args,**kwargs):#因为不知道被装饰的函数有多少个参数,所以这个地方使用非固定参数
func(*args,**kwargs)
return warpper
@timer # index = timer(index)
def index(msg):
print('in the index',msg)
@timer # home = timer(home)
def home(user,msg):
print('in the home %s %s'%(user,msg))
index('hello')
home('tom',msg='XXXX')
1.4、被装饰的函数有返回值
import time,functools
#有返回值的装饰器
def timer(func):
def warpper(*args,**kwargs):#因为不知道被装饰的函数有多少个参数,所以这个地方使用非固定参数
res = func(*args,**kwargs)
return res #因为被装饰的函数有返回值,所以将运行结果返回
return warpper
@timer # index = timer(index)
def index(msg):
print('in the index',msg)
@timer # home = timer(home)
def home(user,msg):
print('in the home %s %s'%(user,msg))
return 1 #被装饰的函数有返回值
index('hello')
res = home('tom',msg='XXXX')
print(res)
1.5、多个装饰器套用
@deco3
@deco2
@deco1 #func1 = deco1(index)--> func2 = deco2(func1) -->index = deco3(func2) index = deco3(deco2(deco1(index)))
def index():
print('in the index')
index()
装饰器小知识点:
函数被装饰了之后,如果使用help()来查看被装饰函数的内容时此时显示的是装饰器函数的内容,此时可以用到Python中的一个模块“functools”
import time,functools#导入functools模块
def timer(func):
@functools.wraps(func)#使用warps方法后,在使用help查看index函数时,查看的是index的函数信息。
def wrapper(*args,**kwargs):
start_time = time.time()
res = func(*args,**kwargs)
stop_time = time.time()
print('运行时间:%s'%(start_time-stop_time))
return res
return wrapper
@timer # index = timer(index)
def index(msg):
'''
装饰器测试
:param msg:
:return:
'''
print('in the index',msg)
index('hello index')
2、有参装饰器
有参装饰器,其实是在原来无参装饰器的基础上在套上一层函数。
以下代码其实有个bug,俩被装饰的函数,每次调用都会提示输入用户名和密码
def auth(type_file):
def auth_deco(func):
def warpper(*args,**kwargs):
username = input("请输入用户名:")
password = input("请输入密码:")
if type_file == 'file':
if username == 'xiaoling' and password =='123':
res = func(*args,**kwargs)
return res
elif type_file == 'ldap':
print("使用的是ldap")
return func(*args,**kwargs)
return warpper
return auth_deco
@auth('file') #有参装饰器
def index(msg):
print('in the index')
index('hello')
@auth('ldap') #有参装饰器
def home():
print('in the home')
home()