python的高级2——函数作为对象
函数作为变量
1、首先了解python中的一等对象(一等公民)
- 运行时创建
- 能赋值给变量 或者 数据结构里的元素
- 能作为参数传给函数
- 能作为函数的返回结果
综上,简单来讲就是和整数,字符串、列表一样,能够直接使用的对象
2.、 高阶函数:接受函数作为参数 或者 把函数作为返回结果的函数是高阶函数(higher-order function)
- 高阶函数的特点
- 能够抽象和封装常见的行为模式
- 是代码更简洁、表达力更强
- 支持函数组合,便于构建复杂的操作链
# 根据单词长度排序一个列表
fruits = ["strawberry", "fig", "apple", "cherry", "raspberry", "banana"]
sorted(fruits, key=len)
# 把单词当成 反过来的单词 去排序,但是单词本身并没有进行反转
sorted(fruites ,key = lambda word: word[::-1])
# sorted就是python自带的一个高阶函数,他接收了一个实现列表反转的匿名函数
3、映射函数:map()
map()
允许你对一个可迭代对象(如列表、元组等)中的所有元素 应用一个指定的函数,并返回一个包含所有结果的新迭代器(列表、集合、元组等)。
即 : 将函数映射到一个可迭代对象的所有元素上- 使用方法:
map(function(要应用的函数),iterable(一个或者多个可迭代的对象))
- 主要的特点:
- 惰性求值(python3中):
map
返回的是一个迭代器,而不是立即计算的列表 - 不改变原有的数据:
map
函数生成的是新结果,而不是直接修改原来的可迭代对象(以列表代称) - 函数式风格:避免显式循环,代码更加简洁
列表相加的示例:# 两个列表对应元素相加 list1 = [1, 2, 3] list2 = [4, 5, 6] result = map(lambda x, y: x + y, list1, list2) print(list(result)) # 输出: [5, 7, 9]
- 惰性求值(python3中):
- 性能考虑
- 现在大多数简单的场景用列表推导式代替
map
函数的使用, - 处理数据转换的强大工具,特别适合函数式编程风格和数据处理流水线的时候推荐使用map函数
- 现在大多数简单的场景用列表推导式代替
4、过滤函数:filter()
-
用于过滤序列中的元素,返回一个迭代器对象。
它的是根据指定的函数对序列进行筛选,只保留使函数返回值为True
的元素。即:从可迭代对象中筛选出满足特定条件的元素。 -
使用方法:
filter(function(函数), iterable(可迭代的对象))
, -
主要特点:
- 惰性求值(python3中),因为返回的是迭代器而非列表,因此可以根据需求迭代所需元素
- 保留原顺序:输出元素的顺序与输入一致(仅仅将不符合的元素进行排除,不影响列表中元素的先后顺序)
- 函数作为筛选条件:如果迭代器中的元素应用到函数的返回结果是
True
,则元素被保留;返回结果是False
,则元素被过滤掉。
-
过滤偶数的示例:
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]def is_even(num):return num % 2 == 0even_numbers = list(filter(is_even, numbers)) print(even_numbers) # 输出: [2, 4, 6, 8, 10]
-
性能考虑:
- 对于简单的条件,可以使用列表推导式进行代替通常更加直观
- 对于大数据集来说,
filter
比显示的循环更加高效(与map
类似)
-
filter
与map
经常结合使用,形成数据处理管道(先将数据进行过滤,在对过滤好的数据进行统一的处理):numbers = [1, 2, 3, 4, 5, 6] result = map(lambda x: x**2, filter(lambda x: x % 2 == 0, numbers)) print(list(result)) # 输出: [4, 16, 36]
5、归约函数:reduce()
- 用于累计计算,对序列中的元素,连续使用二元函数,最终缩减到一个值。
python3中需要从functools
中导入 - 核心思想:将序列中的元素从左到右一次组合,最终生成一个累积结果。
- 使用方法:
reduce(function, sequence[ ])
传入的序列如果是空的话,会引发TypeError操作 - 列表扁平化和查找最大值的示例:
# 列表扁平化
list_list= [[1, 2], [3, 4], [5, 6]]
flatten = reduce(lambda x, y: x + y, list_list)
print(flatten) # 输出: [1, 2, 3, 4, 5, 6]# 查找最大值
numbers = [3, 8, 1, 5, 9, 2]
max_num = reduce(lambda x, y: x if x > y else y, numbers)
print(max_num) # 输出: 9
- 性能考虑
- 简单操作:显示的循环更加快捷
- 复杂操作:
reduce
可以提供更加清晰的表达 - 大数据集:
reduce
可以与生成器配合从而节省内存
6、冻结函数:partial()
partial()
函数和reduce
一样是functools
模块中的一个高阶函数,用于固定函数的部分参数,从而生成一个简化版本的函数- 使用方法:
partial(func, *args, **kwargs)
;这里的参数可以通过位置,也可以通过关键字进行传递 - 主要特点:
- 参数预绑定:可以固定函数的部分参数
- 延迟执行:返回一个新的函数,可在后续调用
- 接口简化:减少重复参数传递
- 函数组合:便于创建函数管道
- 基本使用示例:
def greet(greeting, name, punctuation):return f"{greeting}, {name}{punctuation}"hello = partial(greet, "Hello", punctuation="!")
print(hello("Alice")) # 输出: "Hello, Alice!"
# 这里观察一下hello的参数:
print(hello) # 输出:functools.partial(<function greet at 0x0000018F9B0F72E0>, 'Hello', punctuation='!')
# 固定了greet函数的第一个位置参数为“Hello”,和一个关键字参数punctuation为“!”
- 与
map
配合使用
numbers = [1, 2, 3, 4]
add_five = partial(map, lambda x: x + 5)
print(list(add_five(numbers))) # 输出: [6, 7, 8, 9]
# 看一下add_five的参数
print(add_five) # 输出:functools.partial(<class 'map'>, <function <lambda> at 0x0000018F9B0F5800>)
# 固定了map的第一个参数为匿名函数
- 上述两段代码的参数不同,主要是因为partial冻结的是可调用对象的调用方式。
- 第一段代码中固定了
geet
的调用方式(参数1、3都被固定下来了)
-第二段代码中固定了map
的调用方式(传入的第一个参数一定是指定的匿名函数)
- 第一段代码中固定了
7、函数生成器(yield
)
- 含有
yield
的函数都是一个生成器函数 - 在python高级1中有介绍