第三十一篇 二分查找、匿名函数、内置函数、面向过程编程
第三十一篇 二分查找、匿名函数、内置函数、面向过程编程
一、二分查找
在一个从小到大排列的数字列表中查找指定的数字,如果列表规模极大,用for循环遍历查找效率过低,而用二分法查找则可以将问题规模极快缩小,也就是每次选取剩余列表的中间值和指定数字作比较,然后通过比较大小来一步步缩小与指定数字的距离,直到找到指定数字
lis = [i for i in range(100)] # 列表生成式
# 二分法用递归实现
def find_num(num, lis):
# 如果列表长度为零,则终止函数
if len(lis) == 0:
print('没有找到')
return
# 也可以用另一个终止逻辑
'''
if len(lis) == 1 and lis[0] != num:
print('no find')
return
'''
mid_ind = len(lis) // 2 # 取列表的中间值的索引
mid_num = lis[mid_ind] # 通过索引找到中间值
# 中间数字小于指定数字,截取中间数字后面的列表进行递归
if mid_num < num:
lis = lis[mid_ind + 1:]
find_num(num, lis)
# 中间数字大于指定数字,截取中间数字前面的列表进行递归
elif mid_num > num:
lis = lis[:mid_ind] # 顾头不顾尾
find_num(num, lis)
# 中间数字等于指定数字,则找到指定数字
else:
print('find')
# 调用递归函数
find_num(20, lis)
二、匿名函数
1、有名函数
我们之前使用的都是有名函数,它是基于函数名使用
def f():
pass
f()
2、匿名函数
匿名函数,它没有绑定名字,使用一次即被收回,但是加括号也可以像有名函数一样使用,但它的应用场景是和内置函数联用
lambda x,y:x+y # 传入x,y两个参数,让他们相加
print(type(lambda x,y:x+y)) # <class 'function'>
print((lambda x,y:x+y)(2,3)) # 5
3、与内置函数联用
匿名函数通常与max() 、min()、sorted() 、filter() 、map()等方法联用
# 工资字典
salary1_dic = {
'king':1.5,
'jojo':3,
'bobo':2.2,
'tom':1.8,
}
1.max() 计算最大值
- 1.首先将可迭代对象变成迭代器对象
- 2.将迭代器对象的
__next__()方法的值作为参数传给key参数指定的函数,然后将该函数的返回值当作判断依据
# 以上面的工资字典为例,求工资最高为多少
# 如果不给key具体的函数参数,则会以字典的key排序
res = max(salary1_dic,key = lambda name:salary1_dic[name]) # 以value排序并返回key
print(res) # jojo
# 试写max()方法
def dict_max(iterable,key=None):
iterator = iterable.__iter__()
itin = 0
for next_res in iterator:
value_res = key(next_res) # key(next_res) 就是 func(key_res)
if value_res > itin:
value_res,itin = itin,value_res
return itin
def func(k_res):
return salary_dic[k_res]
2.min() 计算最小值
res = min(salary1_dic,key = lambda name:salary1_dic[name])
print(res) # king
3.sorted() 排序
- 1.先将可迭代对象变成迭代器对象
- 2.res = 迭代器对象._next_(),或者res = next(iterator) ,然后将res当作参数传给第一个参数指定的函数,再然后将该函数的返回值当作判断依据
res = sorted(salary1_dic,key = lambda name:salary1_dic[name])
print(res) # ['king', 'tom', 'bobo', 'jojo']
4.filter() 过滤
- 1.先将可迭代对象变成迭代器对象
- 2.res = 迭代器对象._next_(),或者res = next(iterator) ,将res当作参数传给第一个参数指定的函数,然后filter会判断函数的返回值的真假,如果为真则留下
lis = ['joo',' ','tom','bobo']
res = filter(lambda x:x.replace(' ',''),lis)
for i in res:
print(i)
'''
joo
tom
bobo
'''
5.map() 映射
- 1.先将可迭代对象变成迭代器对象
- 2.res = 迭代器对象._next_(),或者res = next(iterator) ,将res当作参数传给第一个参数指定的函数,然后将该函数的返回值作为map()方法的结果之一
# 先用ord()方法获取英文字符的整数值(或查看ASCII码对照表)
l1 = [chr(i) for i in range(97,123)] # a到z的整数值,通过chr()方法转为字符
l2 = [chr(j) for j in range(65,91)] # A到Z的整数值,通过chr()方法转为字符
res = map(lambda cha1,cha2:f'{cha1} {cha2}',l1,l2)
print(list(res)) # 转成列表打印更直观
'''['a A', 'b B', 'c C', 'd D', 'e E', 'f F', 'g G', 'h H', 'i I', 'j J', 'k K', 'l L', 'm M', 'n N', 'o O', 'p P', 'q Q', 'r R', 's S', 't T', 'u U', 'v V', 'w W', 'x X', 'y Y', 'z Z']'''
三、内置函数
1.想了解更多内置函数,请登陆:https://docs.python.org/3/library/functions.html?highlight=built#ascii自行查看
2.掌握
- 1.bytes() 解码字符
# 一般方法
res = '你好,世界'.encode('utf8')
print(res) # b'\xe4\xbd\xa0\xe5\xa5\xbd\xef\xbc\x8c\xe4\xb8\x96\xe7\x95\x8c'
# 内置函数方法
# bytes('你好,世界',encoding = 'utf8') # 一个内容参数,一个编码格式参数
print(bytes('你好,世界',encoding = 'utf8'))
- 2.chr()/ord()
- 对照ASCII码表,chr()的作用是将数字转成对应的字符;ord()将字符转成对应的数字
print(chr(99))
print(ord('C'))
- 3.divmod() 前数除以后数分别取整和取余
print(divmod(3,3)) # 前数除以后数,前者取整,后者取余
- 4.enumerate() 带有索引的迭代
l = ['HUAWEI','IPHONE','OPPO','SAMSUNG','NOKIA']
for i in enumerate(l):
print(i)
'''
(0, 'HUAWEI')
(1, 'IPHONE')
(2, 'OPPO')
(3, 'SAMSUNG')
(4, 'NOKIA')
'''
- 5.eval() 只作用于字符串,将字符串的首尾的引号去除,字符串里面的数据去掉引号后必须具有具体的数据类型
l = '["a","k",3]'
print(eval(l)) # ['a', 'k', 3]
- 6.hash() 是否可哈希
# 可变是不可哈希,不可变是可哈希
print(hash(6)) # True
3.了解
- 1.abs() 求绝对值
- 2.all() 可迭代对象内的元素全为真,则返回真
- 3.any() 可迭代对象中有一个元素为真,则为真
- 4.bin()/oct()/hex() 转二进制、转八进制、转十六进制
- 5.dir() 列举导入模块的所有功能
- 6.frozenset() 将集合变为不可变类型的集合
- 7.globals()/locals() 查看全局名字/查看局部名字
- 8.pow(x,y,z) 返回值为(x**y)%z
- 9.round() 将数字四舍五入
- 10.slice() 切片
- 11.sum() 求和
- 12._import_() 通过字符串导入模块
print(abs(-3))
print(all(['k','']))
print(any(['tim','']))
print(bin(2))
print(oct(8))
print(hex(16))
time = __import__('time')
print(dir(time))
s = {35,'fks','jojo'}
print(frozenset(s))
print(globals())
def func():
x = 1
print(locals())
func()
print(pow(5,2,2))
print(round(6.6))
lis = ['a','b','c','d','e','f']
s = slice(1,3,1)
print(lis[s]) # lis[1:3:1]
print(sum([3,5,6,2]))
4.面向对象知识点
- 1.class method
- 2.static method
- 3.property
- 4.delattr
- 5.hasattr
- 6.getattr
- 7.setattr
- 8.isinstance()
- 9.issubclass()
- 10.object()
- 11.super()
四、面向过程编程
1.按照一定的顺序,顺序中的每一步都可以看成函数,这个函数的输入是上一个函数的输出,这就叫面向过程编程
2.优点:
- 1.逻辑清晰,简单明了
- 2.每个函数可以独立的写出来
3,缺点:
- 1.相互之间会有一定的联系,上一步中断了,下一步也就中断了
- 2.有一个功能改变了,其他的功能也要改变
- 3.可扩展性差
def enter():
username = input('请输入用户名:').strip()
password = input('请输入密码:').strip()
return username,password
def file_append(filename,content):
with open(filename,'a',encoding='utf8') as fa:
fa.write(content)
def file_write(filename,content):
with open(filename,'w',encoding='utf8') as fw:
fw.write(content)
def file_read(filename):
with open(filename,'r',encoding='utf8') as fr:
data = fr.read()
def register():
username,password = enter()
file_append('text.txt',f'{username} {password}\n')
return True
def login():
user_dic = dict()
username,password = enter()
data = file_read('text.txt')
for user in data:
user_list = user.split()
user_dic[user_list[0]] = user_list[1]
if user_dic.get(username) and password == user_dic[username]:
print('bingo')
break
else:
print('error')

浙公网安备 33010602011771号