Python杂项知识
Python杂项知识
主要内容:
- 函数递归
- 二分法
- 三元表达式
- 列表推导式
- 字典推导式
- 匿名函数
- 常用的内置函数
1. 函数递归
函数递归的本质就是一个自己调用自己的过程,直到找到结果后然后返回。递归通常可以分为2个阶段,回溯和递推。所谓回溯就是指一层一层往下回溯,回溯的过程中是将问题复杂度降低的过程,直到达到一个门限,然后返回,根据最后的返回结果一步步回推,达到解决最开始的问题。
总结一下递归函数,就是递归一定要有一个基线条件,无限的递归没有任何意义。递归是解决某些问题很好的手段,用递归写出的代码也很简洁优雅。但是递归的过程很消耗资源,Python中递归的默认最大深度大概就在997左右,所以除非不得已要使用递归,否则选择把递归转化为迭代法效率会高很多。
下面是几个小例子,先体验递归的代码简洁度。首先是一个传统的例子,猜年龄,每一个人都比后一个人大2岁,最后一个人告诉了你他的年龄。所以求第一个人的年龄。分析一下,这个例子就是可以写出简单的递推式子。f(n) = f(n-1) + 2, 知道了最后一个人的年龄,就想相当于知道了所有其他人的名字。
def get_age(n):
return 18 if n == 1 else get_age2(n - 1) + 2
print('第五个人年龄: ', get_age(5))
递归的精髓就是能把看起来很复杂的问题提炼的很简单明了,只要知道递推公式,然后知道最后的基线条件,那么递归函数写起来就会的应顺手。
下面又是一个经典的利用递归求解汉诺伊塔问题。
count = 1
def hanoi(n, source, mid, dest):
global count
if n == 1: # 最后的终止条件一定是把最左边的搬到最右边的柱子
print(count, source, '->', dest)
return
hanoi(n-1, source, dest, mid) # 重复的借助右边的柱子把左边的柱子搬到中间的柱子
count += 1
print(count, source, '->', dest)
count += 1
hanoi(n-1, mid, source, dest) # 最后把剩下的在中间的柱子借助左边柱子搬到右边柱子
hanoi(4, 'A', 'B', 'C')

可以看到利用递归后,看似复杂的汉诺伊问题就简单的在10行代码之内解决了。合理的运用递归可以解决许多问题。
2. 二分法
二分法就是要在一堆已经排好序的数据中查找我们指定的数据。通用的查找方法就是在容器中顺序查找,但是这种查找效率太低,在数据量很大的情况下,查找次数太多,因此二分法就是一种高效查找效率的算法。它的思想就是每次把所有数据分成两半,取中间那个数和目标数据对比,比目标数据大的就往左边找,否则右边找,依次类推,查找范围会越来越少,直到最后找不到或找到为止。
按照二分法的思路,会有两种解法,递归法和迭代法。先写递归法。
def get_num(lst, target):
middle_index = len(lst) // 2
if not lst: # 当列表为空时,就说明找不到
print('找不到')
return
if lst[middle_index] < target:
get_num(lst[middle_index+1:], target)
elif lst[middle_index] > target:
get_num(lst[:middle_index], target)
else:
print('find it %d' % target)
def binary_search(lst, des):
"""查到返回索引,否则返回-1"""
right = len(lst) - 1
left = 0
while left <= right:
mid = (right + left) // 2
if lst[mid] == des:
return mid
elif lst[mid] < des:
left = mid + 1
else:
right = mid - 1
return -1
3. 三元表达式
三元表达式就是对if else语句的一种简写功能,它常用在只有两种结果的简单场景,例如下面的例子所示。
def judge(a, b):
return True if a > b else False
print(1 if 2 > 3 else 0)
三元表达式最终总会返回一个值,此外它虽然支持多个三元表达式嵌套,但是这样写只会增加复杂度,所以最好只用在两个结果的判断上。
4. 列表推导式
列表推导式就是快速生成列表的简易写法,它的通用语法结构是[item for item in 可迭代对象],其中还可以对item添加其他操作,再返回,此外还可以对可迭代对象的元素加一个过滤条件,即最后还可以加if语句。

使用列表推导式生成列表的代码简洁,而且速度非常快,它比我们手动用for循环生成的效率高。
5. 字典推导式
从名字就可以看出字典推导式和列表推导式一样都是快速生成字典的简便写法。语法结构与列表推导式相同。
现有一个需求,需要把存储个人信息的列表和对应的键名一一对应。

此外,python中还有集合推导式,生成式推导式, 使用方法与前两者如出一辙。

6. 匿名函数
匿名函数是指不带函数名的函数,在Python中用关键字lambda定义。匿名函数一般不单独使用,会与一些需要传入函数作为参数的函数一起使用。例如max,min函数等等。
下面是一个获取绝对值最大的数,和乘方后最大的数,结果都是-9.

7. 常用的内置函数
min() 获取可迭代对象的最小值,可以传入key值。
lst = [1, 4, 5, 0, -1, -9] min(lst, key=abs) # 获取绝对值最小的值 Out[29]: 0
map() 把可迭代对象的元素根据传入的函数一一映射出来,生成一个map对象。
m = map(lambda x: x**2, range(5)) m Out[31]: <map at 0x2a8fb607240> list(m) Out[33]: [0, 1, 4, 9, 16]
zip() 传入多个可迭代对象,把相同位置的元素配对,组合成一个个元组返回出来,长度按照木桶原理,取最短的那个。
zip(range(4), ['a', 'b', 'c', 'd'], ['aa', 'bb', 'cc', 'dd', 'ee']) Out[34]: <zip at 0x2a8fb5e0f88> list(zip(range(4), ['a', 'b', 'c', 'd'], ['aa', 'bb', 'cc', 'dd', 'ee'])) Out[35]: [(0, 'a', 'aa'), (1, 'b', 'bb'), (2, 'c', 'cc'), (3, 'd', 'dd')]
reduce() 相当于一个可以把之前生成的结果保存起来依次与其他元素进行累加的函数。这个函数在functools模块,用之前需要导入。
from functools import reduce reduce(lambda x, y: x+y, range(101)) # 实现累加 Out[37]: 5050 reduce(lambda x, y: x * y, range(1, 6), 1) # 实现阶乘 Out[38]: 120

浙公网安备 33010602011771号