第三十一篇 二分查找、匿名函数、内置函数、面向过程编程

第三十一篇 二分查找、匿名函数、内置函数、面向过程编程

一、二分查找

在一个从小到大排列的数字列表中查找指定的数字,如果列表规模极大,用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')
		
posted @ 2019-06-17 11:26  newking_itman  阅读(119)  评论(0)    收藏  举报