Python基础——高阶函数
文章目录
1. 参数详解
1.1 函数中参数的位置遵循原则
- 放在函数圆括号里的变量称为参数。参数实现数据的共享作用。
- 用星号来区分位置参数和命名关键字参数,位置参数必须放在星号后面,参入时只需要对号入座即可。
1.2 可变参数
- 当我们在第一元素时不知道到传入多少个参数时,就可以使用可变参数。
- 常用 *agrs来表示可变参数
- 可以接受零个或多个位置参数
- 可变参数将传入的位置参数封装成元组
def fun(*args):
return sum(args)
1.3 关键字参数
- 解决传入多个关键字参数,参入参数时要加参数名
- 常用*kwargs表示
- 可以接受零个或多个关键字参数
- 关键字参数将传入的关键字参数封装成字典,参数名对应字典中的键、数对应字典中的值。
def fun(**kwargs):
return sum(kwargs.values())
- 关键字参数一定是放在位置参数之后
2. 设计函数
2.1 函数的设计原则
- 函数的设计原则要遵循一个函数只做好一件事,对于返回值没有歧义。
- 添加必要的文档注释,让调用者知道具体实现功能
- 高内聚,低耦合
2.2 函数的调用无副作用
- 函数调用时不要改变传入的参数原来特征
- 调用时可以用拷贝方法
def num_sort(items:list):
items=itmes[::]
2.3 函数要做到高内聚低耦合效果
- 对于一些二元运算在编程中,常常会直接用:+、-、*、/…等,这样就造成高耦合
- 在函数编程中,尽量把上述运算封装成函数,直接调用函数来降低高耦合。
2.4 高阶函数
- 函数可以作为参数传递给函数
- 函数可以作为函数的返回值
- 函数可以赋值给变量
- 实现对原函数的解耦合作用
3. 匿名参数
- 当在编程时遇到一句就能写好的程序,可以直接使用匿名函数
- 定义匿名函数语法:lambda 参数 :表达式,其中参数等同于定义函数时的参数、表达式就是定义函数时的放回值。
- 如图
4. 递归函数
4.1 函数与函数之间的调用原理
- 函数调用栈,实现对函数的调用进行保存
- 遵循栈的先进后出原则
- 调用栈的内存
4.2 何为递归函数
- 递归函数指函数直接或间接的调用自己,叫做递归调用。
- 递归函数在设计要尽快的达到收敛。
- 如果一个函数(通常指递归调用的函数)不能够快速收敛,那么就很有可能产生下面的错误
RecursionError: maximum recursion depth exceeded,最终导致程序的崩溃。
4.3 递归函数的结构及原理
-
结构:
- 递归公式(递归体)
- 收敛条件(递归出口),停止调用的条件
-
原理:包括两个步骤
1. 递归
2. 回溯 -
递归实现斐波拉数列
def fib(n):
"""斐波拉数列
:param n: 第几项
:return: 对应值
"""
if n in (1, 2):
return 1
return fib(n - 1) + fib(n - 2)
if __name__ == '__main__':
for i in range(1, 8):
print(fib(i), end=' ') # 1 1 2 3 5 8 13
- 阶乘
def fac(num: int) -> int:
"""递归调用求阶乘
:param num: 待求阶乘数
:return: 返回对应值
"""
if num == 0:
return 1
return num * fac(num - 1)
- 解释器执行过程
5. 编程应用
5.1 对冒泡排序进行封装
def bubble_sort(items: list, ga=lambda x, y: x > y, ascending=True) -> list:
"""冒泡排序
:param items: 排序的列表
:param ga: 二元运算函数
:param ascending: 排序方式,默认升序
:return: 列表
"""
items = items[:] # 不改变原来的list
for i in range(1, len(items)):
swap = False
for j in range(0, len(items) - i):
# if items[j] > items[j + 1]:
if ga(items[j], items[j + 1]):
items[j], items[j + 1] = items[j + 1], items[j]
swap = True
if not swap:
break
if not ascending:
items = items[::-1]
return items
if __name__ == '__main__':
print(bubble_sort([1, 3, 2, 5, 6, 7, 3], ascending=True)) # [1, 2, 3, 3, 5, 6, 7]
print(bubble_sort([1, 3, 2, 5, 6, 7, 3], ascending=False)) # [7, 6, 5, 3, 3, 2, 1]
names = ['tian', 'yu', 'ping', 'name', 'link', 'relation', 'brother']
print(bubble_sort(names, ascending=False, ga=lambda x, y: len(x) > len(y)))
# ['relation', 'brother', 'link', 'name', 'ping', 'tian', 'yu']
print(bubble_sort(names, ascending=True, ga=lambda x, y: len(x) > len(y)))
# ['yu', 'tian', 'ping', 'name', 'link', 'brother', 'relation']
5.2 对折半查找进行封装
def bin_search(items: list, key: int, cmp=lambda x, y: x - y) -> int:
"""二分查找
:param items: 传入列表
:param cmp:比较大小,解决原函数耦合
:param key: 查找关键字
:return: 找到就返回下标,否则返回-1
"""
high = len(items) - 1
low = 0
while low <= high:
mid = (high + low) // 2
if cmp(items[mid], key) < 0:
low = mid + 1
elif cmp(items[mid], key) > 0:
high = mid - 1
else:
return mid
return -1
if __name__ == '__main__':
nums = [1, 2, 3, 5, 6, 7, 7, 8, 10]
print(bin_search(nums, 3)) # 2
print(bin_search(nums, 7)) # 6
总结
通过函数的学习提高了代码的复用性,高阶函数的使用提高来编程效率。递归调用函数让很多编程问题变得简单,关键是找到递归公式和递归条件,进行调用和回溯。函数作为后面的面向对象编程基础,被类封装成方法进行使用。