1. 闭包
Python 函数是支持嵌套的。如果在一个内部函数中对外部函数作用域(非全局作用域)的变量进行引用,那么内部函数就会被称为闭包。闭包需要满足如下 3 个条件:
- 存在于两个嵌套关系的函数中,并且闭包是内部函数
- 内部函数引用了外部函数的变量
- 外部函数会返回内部函数的函数名
闭包的作用:
- 可以保持程序上一次运行后的状态然后继续执行。
# 直接传参
def func(x):
print(x)
func(5) # 5
# 闭包传参
def foo():
num = 1
def add(n):
nonlocal num
num += n
return num
return add
f = foo()
print(f(1)) # 2
print(f(2)) # 4
2. 装饰器
- 假设我们已经定义了一个函数,后续可能会增加临时的需求,例如插入日志,我们可以增加一个包裹函数,由它来负责这些额外的需求,这个包裹函数就是装饰器。
- 简单来说就是用于拓展原来函数功能的一种函数,目的是在不改变原函数名的情况下,给被装饰对象添加新的功能 。函数装饰器有开发封闭原则:开放是对扩展开放,封闭是对修改封闭。函数装饰器必须遵守的原则:一是不改变被装饰对象的源代码,二是不改变装饰对象的调用方式。
定义一个最基础的函数:
def sum1():
sum = 1 + 2
print(sum)
sum1() # 3
如果我们想查看这个函数执行用了多长时间可以加入 import time 语句查看:
import time
def sum1():
start = time.perf_counter()
sum = 1 + 2
print(sum)
end = time.perf_counter()
print("time used:",end - start)
sum1()
# 结果
3
time used: 1.6200000000000936e-05
定义一个函数 timeit,将 sum1 的引用传递给他,然后在 timeit 中调用 sum1 并进行计时:
import time # 查看程序的运行时间
def sum1():
sum = 1 + 2
print(sum)
def timeit(func):
def test():
start = time.perf_counter()
func()
end = time.perf_counter()
print("time used:", end - start)
return test
sum1 = timeit(sum1)
sum1()
# 结果
3
time used: 1.810000000000006e-05
如上就是一个简单的函数装饰器,我们只需要在定义 sum1 以后调用 sum1 之前,加上 sum1= timeit(sum1),就可以达到计时的目的,这也就是装饰器的概念:我们在没有改变函数的调用方式的情况下就给函数增加了新的功能。但是如果我们需要装饰的函数量比较多,那么语法的输入量就会增大,这里 python 就提供了语法糖:@来降低语句的输出。语法糖在书写的时候应该与被装饰对象紧紧挨着,两者之间不要有空格。
import time
def timeit(func):
def test():
start = time.perf_counter()
func()
end = time.perf_counter()
print("time used:", end - start)
return test
@timeit # python的语法糖 @ 后面加上函数的名字。
def sum1():
sum = 1 + 2
print (sum)
sum1()
# 结果
3
time used: 1.6200000000000936e-05
- 如果多个装饰器应用在一个函数上,调用顺序是从下至上。
@wrap_one
@wrap_two
def test():
print(‘---test---’)
//执行顺序:
先执行 @wrap_two,后执行 @wrap_one
#---------------------------------------
def wrapper1(func):
def inner(*args,**ksargs):
print('wrapper1')
ret=func()
print('wrapper1')
return ret
return inner
def wrapper2(func):
def inner(*args,**ksargs):
print('wrapper2')
ret=func()
print('wrapper2')
return ret
return inner
def wrapper3(func):
def inner(*args,**ksargs):
print('wrapper3')
ret=func()
print('wrapper3')
return ret
return inner
@wrapper3
@wrapper2
@wrapper1
def fun():
print('func1')
fun()
# 输出结果为:
# wrapper3
#wrapper2
# wrapper1
# func1
# wrapper1
# wrapper2
# wrapper3
- 装饰有参数的函数
def wrap(func):
def inner(a,b):
print("开始验证权限")
func(a,b)
return inner
@wrap
def test(a, b):
print("a=%d,b=%d"%(a, b))
test(1,2)
# 结果
开始验证权限
a=1,b=2
- 带有返回值的装饰器
def func(function_name):
def func_in():
return function_name()
return func_in
@func
def test():
return 'hello world'
- 带有参数的装饰器
- 如果给装饰器添加参数,需要增加一层包装,先传递参数,然后再传递函数名。
def out_wrapper(flag):
def wrapper(func): # 装饰器函数,func 为被装饰函数
def inner(*args, **kwargs):
#被装饰函数前需要添加的内容
ret = func(*args, **kwargs) # 被装饰函数
#被装饰函数后需要添加的内容
return ret
return inner
return wrapper
3. 常见 Python 内置函数
3.1 map 函数
- map 函数会根据提供的函数对指定的序列做映射。
- map 函数的定义如下:
map(function, iterable,…)
//参数 function 表示函数的名称,参数 iterable 可以是序列、支持迭代的容器或者迭代器。
- map 函数的作用是以 iterable 中的每个元素调用 function 函数,把每次调用后返回的结果保存为迭代器对象。
示例代码:
func = lambda x:x+2
result = map(func, [1,2,3,4,5])
print(list(result))
# [3, 4, 5, 6, 7]
上述代码执行过程:
https://www.cnblogs.com/lincappu/p/8179475.html
https://www.runoob.com/python/python-func-map.html
3.2 filter 函数
- filter 函数会对指定序列执行过滤操作。
- filter 函数的定义如下:
filter(function,iterable)
//function 参数可以是函数的名称或 None;iterable 参数可以是序列、支持迭代的容器或迭代器。
示例代码:
func = lambda x:x%2
result = filter(func, [1, 2, 3, 4, 5])
print(list(result))
# [1, 3, 5]
上述代码执行过程:
https://www.runoob.com/python/python-func-filter.html
https://www.cnblogs.com/hiwuchong/p/8094924.html
3.3 reduce 函数
- reduce 函数会对参数序列中的元素进行累积。
- reduce 函数的定义如下:
reduce(function, iterable[, initializer])
//function 是一个带有两个参数的函数
//sequence 是一个迭代器对象
//initializer 表示固定的初始值
示例代码:
from functools import reduce
func = lambda x, y:x + y
result = reduce(func, [1, 2, 3, 4, 5])
print(result)
# 15
注意:function 参数不能为 None。
在 Python 3 中,reduce 函数已经被从全局名字空间里面移除了,它现在被放置在 fucntools 模块中,使用时需要先引入,格式如下:
from functools import reduce
https://www.runoob.com/python/python-func-reduce.html
https://www.cnblogs.com/apollo1616/articles/9785335.html
参考:
https://www.cnblogs.com/sweet-i/p/11177063.html