递归函数
在函数中调用函数自身;递归函数一定要写终止条件,否则将产生无限递归即死循环。
# 阶乘 6*5*4*3*2*1 def func(n): if n == 1: return 1 else: return n * func(n - 1) # 累加把*换成+即可 print(func(6)) # 6*5*4*3*2*1 = 720 import sys # 获取最大递归深度 res = sys.getrecursionlimit() print(res) # 1000 # 可以通过setrecursionlimit去设置递归最大深度 # 但是要考虑内存能否满足条件,内存满了就会停止,一般不会修改这个 # sys.setrecursionlimit(5000) # Python中递归效率比较低,不推荐使用递归 # 每次调用函数都需要临时开辟一块内存去保存函数运行中的数据,无论函数是否相同的参数去重复调用 # 直到递归全部运行完毕才去释放内存 # 针对这种情况可以使用 缓存装饰器 去提升递归函数的运行效率 # 优化运行机制,把调用函数对于相同参数重复调用的,无需重新函数计算(无须新开辟内存),直接返回之前缓存的返回值 # 如果必须使用递归函数去解决问题时,可以结合实际情况选择使用缓存装饰器,来大大提高运行效率 from functools import lru_cache @lru_cache(maxsize=128) # maxsize参数指调用时递归占多少内存 def func_lru(n): if n == 1 or n == 2 or n == 3: return n else: return func(n - 1) + func(n - 2) + func(n - 3) func_lru(50)
斐波那契数列指的是这样一个数列0,1,1,2,3,5,8,13,21,34...这个数列从第3项开始,每一项都等于前两项之和
def fei(x): if x <= 0: return '无' elif x == 1 or x == 2: return 1 else: return fei(x - 1) + fei(x - 2)
纯函数
函数的返回结果只依赖于它的参数,并且在执行过程中没有副作用。
三个原则
1、变量都只在函数作用域内获取,或者作为函数的参数传入
2、相同的输入保证相同的输出
3、不会产生副作用,不会改变被传入的数据或者全局变量的其他数据
函数的副作用
访问了函数外的数据,对外部数据进行了操作改变了系统环境
纯函数的作用就是降低代码的耦合度(代码的耦合度,是指代码中的单元代码的紧密程度,其中一个单元代码的更改对其它单元代码的影响力与作用)
# 纯函数 def func(a, b): return a + b # 不是纯函数,使用了外部变量 c = 100 def func1(a, b): return a + b + c # 不是纯函数,调用函数后就改变了外部数据 li = [] def func2(a, b): li.append(a) li.append(b) return a + b
匿名函数(lambda 表达式)
语法 lambda 参数: 返回值
用来定义一些比较简单,不会重复使用的函数,通常结合内置函数filter(过滤器函数,传参第一个要传函数或者None,第二个参数要传可迭代对象)使用(这种即为函数当做参数使用);用完即销毁,释放内存。
def fun(a, b): # 普通函数 return a + b # 等同于上面的fun()函数;冒号之前的a,b 代表传入的参数;冒号之后的a+b代表返回值 f = lambda a, b: a + b print(f(11, 22)) # 33 # 匿名函数另一种写法,后面(22,33)代表直接传参,很少使用这种 res = (lambda a, b: a + b)(22, 33) print(res) # 55 lis = [1, 2, 3, 4, 5, 6, 7, 8] # lis可迭代对象,在此处相当于for循环去赋值给前面的x,判断x>3为True就过滤出来,如果不成立就不要这个数据 res = filter(lambda x: x > 3, lis) print(res) # <filter object at 0x0000029EF2398FA0> 过滤器对象 print(list(res)) # [4, 5, 6, 7, 8] # filter(lambda x: x > 3, lis) 可以解释为以下两行代码 # for i in lis: # res1 = (lambda x: x > 3)(i) # 还可以结合or或者三目运算符处理一些简单的逻辑 res1 = lambda x: x * 10 or 5 print(res1(0)) # 5 res2 = lambda x: x * 10 if x > 5 else x * 2 print(res2(6)) # 60 if条件成立就执行if之前的语句 print(res2(4)) # 8 不成立就执行else之后的语句
常用内置函数
abs() 获取绝对值
all() 传入一个可迭代对象,迭代对象内所有元素为真,返回True
any() 传入一个可迭代对象,迭代对象内只要有一个元素,返回True
map() 传入一个函数和一个或多个可迭代对象,会根据提供的函数对指定序列做映射,返回的是迭代器
zip() 聚合打包,会把每个可迭代对象内索引位置相同的聚合在一起,返回的是迭代器,可以使用list()生成列表,传入两个可迭代对象时可以使用dict()转为字典,前提是k值为不可变数据类型
print(abs(-99)) # 99 获取绝对值 a = 1 b = 2 c = 3 print(all([a, b, c])) # True 可以代替 if a and b and c print(any([a, b, c])) # True 可以代替 if a or b or c print(map(float, [1, 2, 3, 4])) # <map object at 0x000001B30E5AEAF0> print(list(map(float, [1, 2, 3, 4]))) # [1.0, 2.0, 3.0, 4.0] 把列表内数据转成float类型 # [3, 7, 11, 15, 19] 提供了两个列表,对相同位置的列表数据进行相加 print(list(map(lambda x, y: x + y, [1, 3, 5, 7, 9], [2, 4, 6, 8, 10]))) def square(x): # 计算平方数 return x ** 2 map(square, [1, 2, 3, 4, 5]) # 计算列表各个元素的平方,返回迭代器<map object at 0x0000020BBF26E970> print(list(map(square, [1, 2, 3, 4, 5]))) # [1, 4, 9, 16, 25],使用 list() 转换为列表 print(list(map(lambda x: x ** 2, [1, 2, 3, 4, 5]))) # [1, 4, 9, 16, 25],使用 lambda 匿名函数 aa = [1, 2, 3] bb = ['a', 'b', 'c'] cc = [11, 22, 33, 44] print(zip(aa, bb)) # <zip object at 0x0000018D0F8C7D00> print(next(zip(aa, bb))) # (1, 'a') print(dict(zip(aa, bb))) # {1: 'a', 2: 'b', 3: 'c'} print(list(zip(aa, bb, cc))) # [(1, 'a', 11), (2, 'b', 22), (3, 'c', 33)]
li1 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15] # 把li1列表处理成[[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12], [13, 14, 15]] # 方式一、使用推导式+列表切片,设置步长为3 li2 = [li1[i:i + 3] for i in range(0, len(li1), 3)] # 方式二、使用推导式+zip li3 = [list(i) for i in list(zip(li1[0:len(li1):3], li1[1:len(li1):3], li1[2:len(li1):3]))] # 方式三、zip+lambda+map li4 = list(map(lambda x: list(x), zip(li1[0:len(li1):3], li1[1:len(li1):3], li1[2:len(li1):3])))