Python的函数可以分成几种
纯函数
递归函数
内置函数
匿名函数
偏函数
闭包
纯函数
官方文档:https://docs.python.org/zh-cn/3.7/library/functions.html
概念
a.一个函数的返回结果只依赖于它的参数,并且在执行过程中没有“副作用”,那么这个函数就是纯函数
纯函数的三个原则
a.变量都只在函数作用域内获取,作为函数的参数传入
b.不会产生“副作用”,不会改变被传入的数据或者其它数据(全局变量、IO操作)
c.相同的输入保证相同的输出(感觉b实现了c就实现了?)
函数的“副作用”
a.副作用是指函数被调用,并完成了函数既定的计算任务,但同时因为访问了外部数据,尤其是对外部数据进行了写操作,导致外部数据改变,从而一定程度改变了系统环境。比如全局变量和IO操作(例如文件)
例子
纯函数例子
def func(a, b):
return a + b ** 2
print(func(10, 20))
非纯函数1:该函数受到了外部环境(c)的影响
c = 10
def func_two(a, b):
return a + b + c
print(func_two(1, 2)) # 13
c = 100 # 外部修改c的值
print(func_two(1, 2)) # 103 外部变量c改变,函数结果也改变
非纯函数2:函数的副作用,对外部环境(li)产生了影响
number = 10
li = [1, 2, 3]
def func_three(a, b):
li.append(a)
return a + b
print(li) # [1, 2, 3]
print(func_three(10, 20)) # 30
print(li) # [1, 2, 3, 10] 外部变量受到了影响
递归函数
概念
递归函数就是在函数内部调用函数自身,自己调用自己
注意点
a.递归函数一定要设置递归边界(终止条件),否则会死循环
b.Python有最大递归次数,超过就会报错:RecursionError: maximum recursion depth exceeded while calling a Python object
1.用sys.getrecursionlimit()可得知,默认是1000
2.用sys.setrecursionlimit(次数)可设置所需的最大递归次数;但实际能够递归的次数,和电脑内存、函数复杂度有关,每递归一次,就占用一部分内存
3.用为函数提供缓存功能的装饰器:functools.lrt_cache(maxsize=128,typed=false)可对缓存进行处理,能对相同函数传入相同参数的调用时,返回上一次的结果
c.递归实际很少使用,因为性能差
例子
1.不设置递归边界/递归的终止条件
def func_one(n):
print(n)
func_one(n - 1)
func_one(10) # RecursionError: maximum recursion depth exceeded while calling a Python object
2.设置递归边界
def func_two(n):
print(n)
if n == 0:
return
func_two(n - 1)
func_two(10) # 10-0
例子:累加函数
def adds(n):
if n == 1:
return 1
res = n + adds(n - 1)
return res
print(adds(2)) # 3
Python中递归函数有最大递归次数
import sys
print(sys.getrecursionlimit()) # 最大递归次数是1000
sys.setrecursionlimit(4000) # 设置最大递归次数为4000
爬楼梯:一次最多爬3解。输入楼梯阶层,算出有几种爬法
1.不加缓存装饰器处理
def stairs_off(n):
if n == 1: # 1
return 1
elif n == 2: # 1,1 、2
return 2
elif n == 3: # 1,1,1 、1,2、2,1、3
return 4
elif n >= 4: # 4阶层后,爬法等于前面3个阶层的爬法之和
return stairs_off(n - 1) + stairs_off(n - 2) + stairs_off(n - 3)
print(stairs_off(100)) # 1.不加缓存装饰器,7.1G内存被占满,运行几分钟不出结果
2.用缓存装饰器进行处理
from functools import lru_cache
@lru_cache(maxsize=128)
def stairs_on(n):
if n == 1: # 1
return 1
elif n == 2: # 1,1 、2
return 2
elif n == 3: # 1,1,1 、1,2、2,1、3
return 4
elif n >= 4: # 4阶层后,爬法等于前面3个阶层的爬法之和
return stairs_on(n - 1) + stairs_on(n - 2) + stairs_on(n - 3)
print(stairs_on(50)) # 立刻跑出结果:10562230626642
内置函数
文档:https://docs.python.org/zh-cn/3.7/library/functions.html
常用的内置函数:
1.map:会根据提供的函数对指定序列做映射
2.filter:用于过滤序列
3.zip:用于将可迭代的对象作为参数,将对象中对应的元素打包成一个个元组
例子
map
1.把list中的每个元素进行处理
li = [1, 2, 3]
def map_one(n):
return n * 10
参数1:函数、参数2:可迭代对象;
进行的事情:依次把可迭代对象的每个元素当成参数,映射到函数中进行处理,返回的结果,放入到map对象并返回
res = map(map_one, li)
print(list(res)) # [10, 20, 30]
filter
对list的元素进行过滤
li = [1, 2, 3, 65, 56, 3, 23, 234, 5]
def filter_one(n):
return n >= 5
# 担任过滤器的函数的返回值,一定要是布尔值
# 在python中,0、None、[]、{}、()、’'的布尔值都是False,其他的都是True
res = filter(filter_one, li)
根据函数中返回的值是True/False进行处理,如果是True,则返回传入的元素
其他的机制和map一样,返回的是filter对象
print(list(res)) # [65, 56, 23, 234, 5]
zip
title = [‘name’, ‘color’, ‘age’]
cat = (‘小布’, ‘蓝白’, ‘5个月’)
num = [1, 2, 3, 4, 5]
res = zip(title, cat, num)
把多个可迭代对象的相同下标的元素以元组形式进行聚合,返回zip对象
如果多个可迭代对象的元素个数不一致,则根据元素最少的进行聚合
print(list(res)) # [(‘name’, ‘小布’, 1), (‘color’, ‘蓝白’, 2), (‘age’, ‘5个月’, 3)]
匿名函数
概念
python中有一种特殊的函数,不需要使用def进行函数定义,也不需要给函数取名字,用lambda表达式进行定义,这种函数叫做匿名函数。匿名函数写完就使用,即写即用,用完就销毁,不会占用内存空间
匿名函数格式:
lambda 参数: 表达式(也是返回值)
例子
把下面函数改成匿名函数
def fun1(var1):
return var1 * 2
res1 = lambda var1: var1 * 2
print(res1(2)) # 4
返回list中大于5的元素
li = [1, 23, 234, 23, 4, 6, 5]
res2 = filter(lambda n: n > 5, li)