巨蟒python全栈开发-第14天 内置函数2 递归 二分查找
一.今日内容总览
1.内置函数补充
repr() 显示出字符串的官方表示形式
chr() arscii码中的字,转换成位置
ord() arscii码中的位置,转换成字
2.递归
自己调用自己
两个口:递归的入口(参数) 和 出口(return)
属性结构的遍历
3.二分法
掐头去尾取中间
查找效率非常高
二.今日内容大纲
1.内置函数(2)
2.递归
3.二分查找
三.今日内容详解
1.内置函数(2)
(1)字符串强转list或者tuple,注意这里是迭代强转
print(list("胡辣汤")) print(tuple("胡辣汤")) ''' 结果: ['胡', '辣', '汤'] ('胡', '辣', '汤') '''
(2)reversed()
lst = ["河南话", "四川话", "东北", "山东", "上海"] r = reversed(lst)
print(dir(r)) #证明这个函数是生成器
print(list(r)) # 结果:['上海', '山东', '东北', '四川话', '河南话']
(3)
huiwen = "上2自来水来自海上" #加上2的目的是为了测试 s = huiwen[::-1] print(s) # 结果: 上海自来水来自海上 it = reversed(huiwen) # 返回的是迭代器 print(it) #结果: <reversed object at 0x000002E1CA867208> s = "" for el in it: s += el print(s) #结果:上海自来水来自海上 #结果: #上海自来水来自2上 #<reversed object at 0x00000172783A74E0> #上海自来水来自2上
(4)slice
lst = ["河南话", "四川话", "东北", "山东", "上海"] s = slice(3,5) # 切片. 麻烦 print(lst[s]) #结果:['山东', '上海'] s = slice(3,) # 切片. 麻烦 print(lst[s]) #结果:['河南话', '四川话', '东北'] s = slice(3,4) # 切片. 麻烦 print(lst[s]) #结果:['山东']
(5)
格式化输出中的f和format
s = "我叫{name}, 我来自{home}, 我喜欢干{hobby}".format(name="周杰伦", home="台湾", hobby="唱歌") print(s) name = "周杰伦" home="台湾" hobby="唱歌" print(f"我叫{name}, 我来自{home}, 我喜欢干{hobby}")
(6)
center()
s = "门神" s1 = s.center(20) print(s1) '''结果: 门神 '''
(7)
print(format("门神", "^20")) #门神在中间 print(format("门神", "<20")) #门神在左边 print(format("门神", ">20")) #门神在右边 '''结果: 门神 ''' '''结果:门神 ''' '''结果: 门神'''
(8)
print(format(3, 'b')) # ⼆二进制 binary 0b11 print(format(65, 'c')) # 转换成unicode字符 ascii print(format(11, 'o')) # ⼋八进制 0o 13 print(format(11, 'x')) # ⼗六进制(⼩写字⺟) print(format(11, 'X')) # ⼗六进制(⼤写字⺟) print(format(11, 'd')) # ⼗十进制 print(format(11, 'n')) # 和d⼀样 print(format(11)) # 和d⼀样 ''' 结果: 11 A 13 b B 11 11 11 '''
(9)
print(format(123456789, 'e')) # 科学计数法. 默认保留6位小数 表示大的数据 print(format(123456789, '.2e')) # 科学计数法. 保留2位小数(e⼩写) print(format(123456789, '0.2E')) # 科学计数法. 保留2位⼩数(E⼤写) ''' 结果: 1.234568e+08 1.23e+08 1.23E+08 ''' # 浮点计数法 print(format(1.23456789, 'f')) # 浮点数计数法. 保留6位⼩数 print(format(1.23456789, '0.2f')) # ⼩浮点数计数法. 保留2位⼩数 print(format(1, '0.10f')) # ⼩浮点数计数法. 保留10位⼩数 print(format(1.23456789e+10000, 'F')) # ⼩浮点数计数法. ''' 结果: 1.234568 1.23 1.0000000000 INF #无穷大的意思 '''
(10)
a = 0b11 # 数字3 print(type(a)) print(a) ''' 结果: <class 'int'> 3 ''' print(ord("中")) # 20013 print(chr(20014)) ''' 结果: 20013 丮 ''' for i in range(65536): print(chr(i), end= " ") #结果:循环打印出65536个字,不一定全显示,可能只显示一部分
(11)
print(ascii("a")) # 判断出你给的信息是否是ascii print(ascii("冬瓜")) #结果: #'a' #'\u51ac\u74dc'
(12)
# 转义字符 # \n 换行 # \t tab 制表符 # \r 回车 # \" 双引号 # \' 单引号 # \\ \ print('你好, 我叫周杰伦.我来自\\n台湾. 我老婆叫昆凌') # repr() # 还原字符串最官方的效果 # str:python的字符串 # repr: 所有的字符串 #注意:在这里repr和r的作用是一样的,但是原理是不一样的 print(repr("你好. \\n我叫\周杰伦")) # python -> repr() -> cpython c里面. 报错 # print(r"\n\t范德萨发生\r\b\ffdsaf") # 原封不动的显示字符串
2.递归
(1)
#函数就是自己调用自己 def func(): print('我是地瓜') func() func() #官方最大1000,你永远跑不到1000,我实测998
(2)
while 1: print("我不是递归")
(3)
#二叉树:完全二叉树 ''' 病毒:(不要试) f=open(path,mode='wb') f.write(b'1') ''' #树形结构的遍历
(3-1)
import os def func(lujing,n): #'d:/a/' lst=os.listdir(lujing) #打开文件夹,列出该文件夹内的所有文件名 for el in lst: #el是文件的名字,b,c #还原路径 path=os.path.join(lujing,el) #"d:/a/b" if os.path.isdir(path): #判断路径是否是目录 print('...'*n,el) #显示文件夹的名字 func(path,n+1) #再来一次 else: print('...'*n,el) #显示文件 func('D:/a',0)
(3-2)
import os def func(lujing,n): #'d:/a/' lst=os.listdir(lujing) #打开文件夹,列出该文件夹内的所有文件名 # print(lst) #最初用来测试的,['b', 'c', '大冬瓜.txt'] for el in lst: #el是文件的名字,b,c #还原路径 path=os.path.join(lujing,el) #"d:/a/b" if os.path.isfile(path): #判断路径是否是文件(注意,这里的文件不只是文件夹,还有txt等) print('...' * n, el) # 显示文件 else: print('...' * n, el) # 显示文件夹的名字 func(path, n + 1) # 再来一次 func('D:/a',0)
总结:注意上边的红字区别,还有上边注释的理解,反复理解
3.二分查找
(1)
#二分法查找主要的作用就是查找元素 lst=[1,3,5,7,12,36,68,79] num=int(input('请输入你要查找的元素信息:')) for el in lst: if num==el: print('存在') break else: print('不存在') len(lst) #对于计算机,很少的数是无所谓的,但是数以百万&亿计的,就真的有所谓了
(2)
规则,掐头去尾取中间
0 1 2 3 4 5 6 7
lst=[1,3,5,7,12,36,68,79]
n=28
规则,掐头结尾取中间,必须是有序序列
100000000//1亿最多是需要27次比较
(3)
(3-1)
二分法查找 (需要明白和掌握)
lst = [1,3,5,7,12,36,68,79] n = int(input("请输入一个数")) left = 0 right = len(lst) - 1 count=0 while left <= right: mid = (left + right)//2 if n > lst[mid]: left = mid + 1 elif n < lst[mid]: right = mid - 1 else: print("存在") print(count) break count+=1 else: print("不存在") print(count)
(3-2)
递归另类想法
def func(n, lst): left = 0 right = len(lst) - 1 if lst != []: mid = (left + right)//2 if n > lst[mid]: func(n, lst[mid+1:]) # 改变列表 elif n < lst[mid]: func(n, lst[:mid]) #在这里列表取不到最后一个,所以不用减1 else: print("找到了") return else: print("没找到") return n = int(input("请输入你要查找的数:")) func(n, [1,3,5,7,12,36,68,79]) # 78
(3-3)
递归2(需要明白和掌握)
def func(n, lst, left, right): # 递归找到什么是可以变的. 什么是不可以变的 if left <= right: mid = (left + right) // 2 if n > lst[mid]: left = mid + 1 return func(n, lst, left, right) elif n < lst[mid]: right = mid - 1 return func(n, lst, left, right) # 递归如果有返回值. 所有调用递归的地方必须写return else: print("找到了") return mid # 难点 else: print("找不到") return -1 #比较牛掰的想法,找不到返回-1 n = int(input("请输入你要查找的数:")) lst = [1,3,55,98,37,41,2,5,1,4] ret = func(n, lst, 0, len(lst)-1) # 78 print(ret)
(4)
哈希寻找消耗内存,二分法不是最快的,只有这种是最快的
最快的查找方式
lst = [1,3,55,98,37,41,2,5,1,4] print(max(lst)) new_lst = [] for i in range(99): new_lst.append(0) for i in lst: # 1,3,55,98 new_lst[i] = 1 print(new_lst) while 1: i = int(input('请输入你要找的数据')) if new_lst[i] == 0: # 1次 print("不存在") else: print("存在")
结果:
98 [0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1] 请输入你要找的数据98 存在 请输入你要找的数据