高阶函数
递归单数&纯函数&匿名函数&内置函数&偏函数
一、递归函数
- 调用函数自身
- 有一个结束条件
- 能用递归的地方都能用循环解决
- 递归的效率比循环低
代码实例:
# 阶乘
def jie_fun(num):
# 判断等于1 返回1,结束条件
if num == 1:
return num
else:
# 自己调用自己 == num*num-1*num-1-1*num-1-1-1 直到num==1 结束
return num * jie_fun(num - 1)
# 2.斐波那契==无限生兔子
def fbnq_func(index):
"""
根据位置输出斐波那契相应位置的数据
:param index: 位置
:return: value
"""
if index <= 2:
return 1
else:
return fbnq_func(index - 1) + fbnq_func(index - 2)
# 在结合map方法将位置一次传入拿到位置集合
print(list(map(fbnq_func, range(1,8))))
# 或者在函数内实现map方法
def fun_fbnq(index):
"""
:param index: 契数列数列的位置
:return:
"""
def index_num(num):
if num <= 2:
return 1
else:
return index_num(num - 1) + index_num(num - 2)
return list(map(index_num, list(range(1, index + 1))))
二、纯函数
1、纯函数的概念
- 当一个函数的返回结果只依赖于它的参数,并且在执行过程里面没有副作用,这就是纯函。
2、纯函数的三个原则
- 变量都只在函数作用域内获取,作为函数的参数传入
- 不会产生副作用,不会改变被传入饿数据或者其他数据(全局变量)
- 相同的输入保证相同的输出
3、函数的副作用
- 副作用是指函数被调用,完成了函数指定的功能任务,单同时因为访问了外部数据,尤其是因为对外部数据进行了写操作,从而一定程度地改变了系统环境
案例说明:
# 一、函数func1返回结果是两个参数相加的结果--纯函数
def func1(a, b):
return a + b
var=100
# 二、函数返回的结果位参数a和外部变量var相加结果--非纯函数
def func2(a):
return a + var
# 三、甚至修改了外部变量 产生了副作用---非纯函数
def func3(b):
global var
var = var + 1
return b + var
func3(2)
print(var) # >>>101
var1 = 40
# 四、引用了外部变量,导致传入了相同的参数值,输入的结果不一样--非纯函数
def func4(c):
return c + var1
print(func4(10)) # >>50
var1 = var1 + 10
print(func4(10)) # >> 60
三、匿名函数
- 没有名字的函数-通过lambda定义
- 定义极为简单的函数可以直接returen的函数,不能处理复杂逻辑
# 冒号前部分是参数部分;后面是return的部分
res=lambda a, b: a + b
print(res) # <function <lambda> at 0x00000229D0FF78C8>
print(res(1,4)) # >>> 5
四、三目运算符
a=100
print("大于100")if a>100 else print("小于等于100")
五、内置函数
- filter 函数:用于过滤序列
- 需要两个参数,参数一:函数名;参数二:可迭代对象
- 把可迭代对象依次传入函数中,函数内部如果返回True 生成原数据,如果函数内部返回False 数据过滤掉
- 返回一个filter迭代器对象
list_s = ["a", "b", "B", "c", "a"]
def fil(s):
if s != "a":
return True
# 生成一个过滤器对象
result = filter(fil, list_s)
# <filter object at 0x00000209CF96C780>
print(result)
print(list(result)) # ['b', 'B', 'c']
# 结合 lambda 表达式一行搞定
print(list(filter(lambda s: s != "a", list_s)))
- map 函数:会根据提供的函数对指定函数做映射
- 需要两个参数,参数一:函数名;参数二:可迭代对象
- 把可迭代对象依次传入函数中,每一次的执行结果生成出来
- 返回map迭代器对象
str1 = "222222"
def ma(s):
return s + "b"
print(map(ma, str1)) # <map object at 0x000001BCB9B51240>
print(list(map(ma, str1))) # list全部转换出来
# 往往配合匿名函数更加便捷一行搞定返回处理后的新序列
print(list(map(lambda s: s + "b", str1)))
- reduce 函数:也是对每个元素进行反复调用,最后返回最终的值,而map是返回一个迭代器
- 需要两个参数,参数一:函数名;参数二:可迭代对象
- 参数函数有且必须有两个参数
- 把每次处理的结果作为函数的第一个参数在和下个序列里的参数做逻辑处理,知道最后返回最终的值
from functools import reduce
def redu(a, b):
return a * b
#先将1,2 传给a、b,函数返回值传给a,3传给b,依次类推
print(reduce(redu, range(1, 6)))
# 配合lambda 一行代码实现阶乘
print(reduce(lambda a, b: a * b, range(1, 6)))
- zip 函数:用于将可迭代元素的对象作为参数,将对象中对应的元素打包成一个个元组
- 参数为多个可迭代对象
- 把索引相同的数据重新打包在一个个元组中
- 以数量最小的数据为打包节点
- 返回zip迭代器对象
# zip函数
a=["name","age","gender"]
b=["DaBai",18,"男"]
res=(zip(a, b))
print(res) # >>> <zip object at 0x000002D32C9D4788>
print(list(res)) # >>> [('name', 'DaBai'), ('age', 18), ('gender', '男')]
# 长短不一,以长度最小的为节点
c=["帅气","年轻"]
print((list(zip(a, b, c)))) # >>> [('name', 'DaBai', '帅气'), ('age', 18, '年轻')]
六、偏函数
- 用functiontools中的partial类
- 作用:当函数的参数个数太多的时候,且有部分参数是一样的时候,需要简化时,使用partial可以创建一个新的函数,这个新函数可以固定住原函数的部分参数,从而在调用时更加简单
- partial等于把函数按照一定的参数,二次封装返回一个固定了部分参数的此函数
# 比如过滤数据时 --一条数据
li1 = [1, 2, 3, 11, 22, 33]
print(list(filter(lambda x: x > 5, li1)))
# 当需要过滤多条数据的时候,fliter过滤每一条数据时 都要写一个固定的过滤函数参数
# 此时可以把过filter函数的第一个参数 过滤函数用偏函数partial 固定住
# partial:第一个参数需要固定的函数;第二个或更多时函数需要固定的参数
# 返回一个新的固定好部分参数的此函数对象
filter2 = partial(filter, lambda x: x > 5)
li2 = [1, 2, 3, 11, 22, 33]
li3 = [1, 2, 3, 11, 22, 33]
li4 = [1, 2, 3, 11, 22, 33]
# 由于fliter函数的第一个参数条件已经被固定住是:lambda x: x > 5了 此时只需要传可迭代对象参数即可
# partial等于把函数按照一定的参数,二次封装返回一个固定了部分参数的此函数
print(list(filter2(li2)))
print(list(filter2(li3)))
print(list(filter2(li4)))