一 函数的递归调用---二分法
需求:有一个按照从小到大顺序排列的数字列表,需要从该数字列表中找到我们想要的数字,如何更高效???
算法之二分法
算法:是高效解决问题的办法
二分法的思路:
1 先取出列表的中间位置的值,与需要的数字进行比较,如果中间位置的值大于需要的值,那么就在中间值的左侧2 进行比较,如果小于,那么就在中间值的右侧进行比较,如果刚好等于,就输出值。
然后对上述步骤进行循环
list1 = [0,2,5,7,9,11,34]
find_num=2
# 列表中间值的索引位置
def func(find_num,list1):
# 输出每次切分后生成的list1
print(list1)
mid_index = len(list1) // 2
if find_num > list1[mid_index]:
list1 = list1[mid_index+1:]
func(find_num,list1)
elif find_num < list1[mid_index]:
list1 = list1[:mid_index]
func(find_num,list1)
elif find_num == list1[mid_index]:
print(f'找到了{list1[mid_index]},索引为{mid_index}')
elif len(list1) == 0:
print('不存在这个值')
return
func(find_num,list1)
# 如果列表内的值不是按照大小顺序排列的,可以使用sort方法进行排序
list2 = [3,2,8,5,6]
list2.sort()
print(list2)
二 编程思想---面向过程编程
面向过程的编程思想
核心:'过程',指的是做事的步骤:先什么,再什么,后干什么
基于该思想编写程序就好比再设计一条流水线
优点:复杂的问题流程化,进而简单化
缺点:扩展性差,比如生产塑料瓶的汽水流水线想生产易拉罐的汽水
面向过程的编程思想的应用场景
1 不是所有的软件都需要频繁更迭
2 即便一个软件需要频繁更迭,也不代表这个软件所有的组成部分都需要一起更迭
三 函数式编程
1 匿名函数的引入
# Ⅰ 定义一个函数,返回较大的值
def func(x,y):
return x if x > y else y
res = func(3,4)
print(res)
# Ⅱ 能否将上述代码简化?
lambda x,y:x if x > y else y
2 匿名函数的语法格式
lambda 参数:返回值
3 如何调用匿名函数
方式一:内存地址加小括号
(lambda x,y:x if x > y else y)(1,2)
方式二:函数参数
# 如果采用这种方式,为何不定义一个有名字的函数呢
func = lambda x,y:x if x > y else y
res = func(2,3)
方式三:
%99应用场景:匿名函数用于临时调用一次的场景,更多是将匿名函数与其他函数配合使用---max min sorted map filter reduce
Ⅰ 匿名函数与max()/min()
alary = {
'egon':100,
'tank':10,
'jack':11
}
# 需求:找到工资最多的人,然后输出对应的名字
# max()/min(),括号内的参数必须是可迭代对象,底层原理是相当于调用for循环,将最大的值返回
res = max(salary)
print(res)
'''
发现返回的名字是tank,但是工资最多的名字并不是tank,原因是什么?
因为,max方法相当于底层调用了for循环,for循环对字典进行遍历,默认遍历的是key,max会将key进行比大小(ASC)ii,所以需要在max中指定比较的依据--value
'''
# 原理:对字典的key进行遍历,将key当作匿名函数的参数,然后返回key所对应的值
res = max(salary,key=lambda k:salary[k])
print(res)
Ⅱ 匿名函数与sorted()
# 需求:按照工资从低到高的顺序输出名字
# 原理同max()
res = sorted(salary,key=lambda k:salary[k])
print(res)
Ⅲ 匿名函数与map()
list1 = ['egon','tank','lulu']
# 需求将list1中的名字之后加上❤,映射到到新的列表中
# 解决方案一:
list2 = [name+'❤' for name in list1]
print(list2)
list2 = (name+'❤' for name in list1)
print(list2) # 将中括号变成小括号,返回的就是一个生成器
# 解决方案二:利用匿名函数
res = map(lambda name:name+'❤',list1)
print(res) # 得到的是一个生成器
print(next(res))
# map原理:相当于将可迭代对象进行遍历,将每个值当作参数传给匿名函数,返回匿名函数的返回值,得到的是一个生成器
# 这样做的好处是:如果列表中的数据过多的时候,不会发生内存溢出的情况
Ⅳ 匿名函数与filter()
list1 = ['pig','python','cute']
# 需求:将list1中以p开头的元素取出存到新的列表中
# 解决方式一:
list2 = [name for name in list1 if name.startswith('p')]
print(list2)
list2 = (name for name in list1 if name.startswith('p'))
print(list2) # 会得到一个生成器
# 解决方式二:匿名函数+filter
res = filter(lambda name:name.startswith('p'),list1)
print(res) # 得到的是生成器
Ⅴ 匿名函数与reduce():
from functools import reduce
res=reduce(lambda x,y:x+y,[1,2,3],10) # 16
print(res)
res=reduce(lambda x,y:x+y,['a','b','c']) # 'a','b'
print(res)
四 模块
1 什么是模块
模块就是一系列功能的集合体
Ⅰ 内置的模块
Ⅱ 第三方的模块
Ⅲ 自定义的模块
一个python文件本身就是一个模块,文件名m.py,模块名叫m
2 为何要用模块
Ⅰ 内置与第三方的模块拿来就用,无需定义,这种拿来主义,可以极大的提升开发效率
Ⅱ 自定义的模块:可以将程序中的各部分功能提前出来放到一个模块中为大家共享使用,好处是减少了代码冗余,程序组织结构更加清晰
3 自定义模块(python文件)及import使用
import foo
首次导入模块会发生:
1 产生foo的名称空间,将foo.py运行过程中产生的名字都丢到foo的名称空间中
2 执行foo.py
3 在当前文件中产生了foo名字,该名字指向2中产生的名称空间
4 之后的导入,都是直接引用首次导入产生的foo的名称空间,不会重复执行foo文件中的代码
import foo
# 引用:名称空间的关系以定义阶段为准
# 强调1:模块名.名字,指名道姓问某一个模块要名字对应的值,不会与当前名称空间中的名字发生冲突
# 强调2:无论是查看还是修改模块,操作的都是模块本身,都是以原模块为基准的,与调用位置无关
print(foo.x)
print(foo.func)
print(foo.func1)
# 引用多个模块:可以以逗号为分隔符,在一行导入多个模块,但是还是建议逐行导入,不建议在一行导入多个模块
导入模块的规范
# 1 内置模块
# 2 第三方库的模块
# 3 自定义模块
import ... as ....
# 将调用的模块起别名,当模块名较长的时候可以用
import foo as f
模块是第一类对象,和函数对象类似,可以用来给给变量赋值
自定义模块的命名应该采用纯小写+下划线的风格
可以在函数内导入模块,但是函数调用结束后,对应的模块占用的名称空间和内存空间会销毁