一、可迭代对象和迭代器【掌握】
【面试题:简述可迭代对象和迭代器之间的区别和联系】
1.可迭代对象
可以直接作用于for循环的对象统称为可迭代对象【Iterable】
判断方式:isinstance():可以判断一个对象是否是可迭代对象
可迭代对象有:
a.一类是集合类型,比如:list,tuple,dict,set,string等
b.一类是生成器【generator】,包括()和yield的function generator
from collections import Iterable #isinstance(数据,类型) #print(isinstance(10,int)) print(isinstance([],Iterable)) print(isinstance((),Iterable)) print(isinstance({},Iterable)) print(isinstance((i for i in range(10)),Iterable)) print(isinstance("",Iterable)) print(isinstance(10,Iterable)) print(isinstance(True,Iterable))
2.迭代器
不但可以直接作用于for循环,还可以被next函数不断调用返回下一个值,直到最后一个元素获取到
问题:如果通过next将生成器中的元素遍历完成,继续调用next,会出现一个StopIteartion的异常
可以被next调用并返回下一个元素的对象被通称为迭代器【Iterator】
判断方式:isinstance():可以判断一个对象是否是迭代器
from collections import Iterator print(isinstance([],Iterator)) print(isinstance((),Iterator)) print(isinstance({},Iterator)) print(isinstance("",Iterator)) print(isinstance((i for i in range(10)),Iterator)) #正常情况下,只有生成器才是迭代器 #联系:迭代器一定是可迭代对象,可迭代对象不一定是迭代器 print("++++++++++") #iter()可以将list,tuple等转换为迭代器 print(isinstance(iter([]),Iterator)) print(isinstance(iter(()),Iterator)) print(isinstance({},Iterator)) print(isinstance("",Iterator)) #for循环的工作原理:通过不断调用next函数实现的 list1 = [22,33,44,55,66,77] #for # for num in list1: # print(num) #完全等价于:next it = iter(list1) # num1 = next(it) # print(num1) # num1 = next(it) # print(num1) # num1 = next(it) # print(num1) while True: try: #监控区 x = next(it) print(x) except StopIteration: #一旦进入except代码块,则说明迭代器中的元素已经遍历完成,则退出循环 break
二、列表生成式和生成器【掌握】
1.列表生成式
列表生成式:List Comprehesions,是Python内置的专门用来生成列表的工具
语法:[元素的规律 for循环 if判断]
#1.需求:生成一个列表[1,2,3,4,5,6,7,8,9] list1 = list(range(1,10,1)) print(list1) #2.需求:生成一个列表[1,4,9,16,25...] #range的弊端:生成的可迭代对象都具有一定的规律,相当于是数学上的等差数列 #自定义功能 newList1 = [] for i in range(1,10): newList1.append(i ** 2) print(newList1) #列表生成式 list3 = [x ** 2 for x in range(1,10)] print(list3) print(type(list3)) #3.需求:生成一个列表[4,16,36,64.....] #列表生成式的顺序:for---->if判断----》元素的规律 list4 = [x ** 2 for x in range(1,10) if x % 2 == 0] print(list4) #等价于 newList2 = [] for i in range(1,10): if i % 2 == 0: newList2.append(i ** 2) print(newList2) #4.需求:使用双层循环,实现全排列 #排列:从m个元素中取出n个元素【n <= m】,按照一定的顺序进行排列,得到的结果成为排列,如果当m == n的时候,被称为全排列 """ 1 2 3 4 ,从中取出3个元素 123 321 231 213 。。。。 """ #嵌套for循环实现排列 newList3 = [] for i in "ABC": for j in "XYZ": #print(i + j,end=" ") newList3.append(i + j) print(newList3) #列表生成式实现排列 list5 = [i + j for i in "ABC" for j in "XYZ"] print(list5) #练习:使用列表生成式,将下面列表中的字母全部变为小写 l = ["Hello","GOOD","IBM","word"] newList4 = [] for s in l: newList4.append(s.lower()) print(newList4) list6 = [s.lower() for s in l] print(list6) #存在的问题:如果列表中存在其他类型的元素,比如:数字 l = ["Hello",27,"GOOD","IBM",37,True,"word"] list7 = [s.lower() for s in l if isinstance(s,str)] print(list7)
2.生成器
生成器:生成一定数据的容器
意义:Python引入的一个机制,从内存的角度出发,避免生成一批数据造成内存瞬间过大的问题,如果在需要数据的时候,只需要去生成器中获取,生成器会根据提前写好的算法生成一批数据
定义生成器的两种方式
a.():将列表生成式中的[]---->()
b.yield:借助于函数
#1. #列表生成式 l = [x for x in range(10)] #生成器 ge1 = (x for x in range(10)) # print(ge1) # print(next(ge1)) # print(next(ge1)) #2. #yield:让步,暂停 def test(n): for x in range(1,n + 1): yield x print(x) print("hello") #注意1:在一个函数中使用yield,相当于设定了返回值,返回的是一个生成器对象 t = test(5) print(t) print("获取:",next(t)) print("获取:",next(t)) # for i in t: # print("获取:",i) """ 工作原理:每次调用next函数或者使用for循环获取数据,函数生成器会走到yield会暂停, 将yield后面的值返回,代码停止,只有当下次再调用next或者for循环的时候,函数生成器再从yield下面的代码执行 """
三、函数递归
递归函数:一个会调用自身的函数被称为递归函数
递归调用:一个函数,调用自身,过程被称为递归调用
递归包含了一种隐式的循环,它会重复执行某段代码,但是这种重复无须条件控制
但凡可以用循环解决的问题,可以递归转换
使用递归解决问题的思路:
a.找到一个可以让隐式循环停止下来的临界值
b.找到两次循环之间的规律【公式/等式】
#1 # def text(): # print("fhjadhf") # text() # text() """ [Previous line repeated 993 more times] File "C:/Users/Administrator/Desktop/XA-Python1807/Day5Code/funcDemo01.py", line 3, in text print("fhjadhf") RecursionError: maximum recursion depth exceeded while calling a Python object """ #2.需求:报一个数,输出对应的数,如:5---->5 9---->34 """ 斐波那契数列 1 2 3 4 5 6 7 8 9 10 11 1,1,2,3,5,8,13,21,34,55,89.。。。。。 规律: 1.第一个位置和第二个位置上的数是固定的,都是1 【临界值】 2.第n个位置上的数 = 第n - 1个位置上的数 + 第n - 2个位置上的数 假设func(num) 分析: func(1) ---- >1 func(2) ----->1 func(3)= func(2) + func(1) = 1 + 1 --->2 func(4) = func(3) + func(2) = func(2) + func(1) + func(2) = 1 + 1 + 1 --->3 ... func(7) = func(6) + func(5) func(6) = func(5) + func(4) func(5) = func(4) + func(3) func(4) = func(3) + func(2) func(3) = func(2) + func(1) .... func(n) = func(n - 1) + func(n -2) n>=3 """ def func(n): print(n) if n == 1 or n == 2: return 1 else: result = func(n - 1) + func(n -2) return result print(func(11)) #练习:使用递归计算1~某个数之间所有整数的和 def add1(num): total1 = 0 n = 1 while n <= num: total1 += n n += 1 return total1 print(add1(100)) #递归求和 """ 1+2+3+4+5 add(1) + 0 = 1 add(2)= add(1) + 2 add(3) = add(2) + 3 ... add(n) = add(n - 1) + n """ def add2(n): if n == 1: return 1 else: return add2(n - 1) + n print(add2(100))
四、栈与队列
栈【Stack】:限定在表的一端进行插入和删除的线性表,类似于一个开口向上的容器
队列【Queue】:限定在表的一端进行插入,在表的另一端删除的线性表,类似于一个水平放置的水管
线性表:是一种线性结构,同一个线性表中的数据类型相同并且满足一对一的逻辑关系
【面试题:栈和队列的相同点和不同点】
相同点:
a.都是线性结构
b.插入操作都限定在表尾进行
c.管理模式相同
d.插入和删除的时间复杂度都是O(1),在空间复杂度上是一样的
不同点:
a.删除数据的位置不同,栈的删除在表尾进行,队列的删除在表头进行
b.应用场景不同:
栈的应用场景:变量,函数,表达式的转换或者求值
队列的应用场景;计算机中各种资源的分配和管理
#先今后出,后进先出 mystack = [] #压栈【入栈】【向栈中存储数据】 mystack.append(11) print(mystack) mystack.append(22) print(mystack) mystack.append(33) print(mystack) mystack.append(44) print(mystack) #出栈【从栈中删除数据】 mystack.pop() print(mystack) mystack.pop() print(mystack) mystack.pop() print(mystack) mystack.pop() print(mystack)
#先进先出,后进后出 import collections #集合 #创建队列 myqueue = collections.deque([11,22,33]) #入队【向队列中添加数据】 myqueue.append(44) print(myqueue) myqueue.append(55) print(myqueue) myqueue.append(66) print(myqueue) #出队【从队列中删除数据】 popleft myqueue.popleft() print(myqueue) myqueue.popleft() print(myqueue) myqueue.popleft() print(myqueue) myqueue.popleft() print(myqueue)
五、目录遍历
os:主要操作磁盘上的文件或者目录
1.递归遍历
#递归遍历目录 import os def getAll(path): #判断指定的路径是否是目录 if os.path.isdir(path): #获取当前路径下所有的内容 fileList = os.listdir(path) #print(fileList) #遍历 for fileName in fileList: #print(fileName) #根据已知的路径和文件名称进行路径的拼接 filePath = os.path.join(path,fileName) #判断是否是目录 if os.path.isdir(filePath): print("目录:", fileName) #继续判断,获取内部的内容 getAll(filePath) else: print("文件:",fileName) else: print("文件:",path) if __name__ == "__main__": path = r"C:\Users\Administrator\Desktop\XA-Python1807" getAll(path)
2.栈模拟递归遍历
深度遍历
#栈模拟递归遍历:每次将目录路径添加到栈中,如果要进一步获取,则将路径从栈中移除【pop】 #递归遍历目录 import os def getAll(path): if not os.path.isdir(path): print("文件:",path) return #定义一个空栈 stack = [] #将初始路径添加到栈中 stack.append(path) while len(stack) != 0: #从栈中取出数据,移除的是最后一个元素 dirpPath = stack.pop() #获取初始目录下所有的内容 fileList = os.listdir(dirpPath) #遍历 for fileName in fileList: #拼接路径 filePath = os.path.join(dirpPath,fileName) #判断是否是目录 if os.path.isdir(filePath): #将目录的路径添加到栈中 print("目录:",fileName) #将目录的路径继续添加到栈中 stack.append(filePath) print(stack) else: print("文件:",fileName) if __name__ == "__main__": path = r"C:\Users\Administrator\Desktop\XA-Python1807" getAll(path)
3.队列模拟递归遍历
广度遍历
#队列模拟递归遍历:每次将目录路径添加到队列中,如果要进一步获取,则将路径从队列中移除【popleft】 #递归遍历目录 import os,collections def getAll(path): if not os.path.isdir(path): print("文件:",path) return #定义一个空栈 queue = collections.deque() #将初始路径添加到栈中 queue.append(path) while len(queue) != 0: #从栈中取出数据,移除的是第一个元素 dirpPath = queue.popleft() #获取初始目录下所有的内容 fileList = os.listdir(dirpPath) #遍历 for fileName in fileList: #拼接路径 filePath = os.path.join(dirpPath,fileName) #判断是否是目录 if os.path.isdir(filePath): #将目录的路径添加到栈中 print("目录:",fileName) #将目录的路径继续添加到栈中 queue.append(filePath) print(queue) else: print("文件:",fileName) if __name__ == "__main__": path = r"C:\Users\Administrator\Desktop\XA-Python1807" getAll(path)
六、模块
1.包
作用:
a.组织文件
b.避免多个文件或者目录命名冲突
区别普通文件夹:init.py文件,为了标记当前文件夹是一个包,前期该文件一般是空的,Django中需要进行项目的配置
2.自定义模块
实质上一个.py文件就是一个模块
模块存在的意义:
a.将相同或者相似功能的代码封装到一个模块中
b.方便后期的维护
c.提高了代码的可读性
d.避免函数名和变量名的冲突
e.引用其他第三方的模块【系统模块,自定义模块,第三方模块:在使用之前一般需要进行安装】
系统模块:math,os,random,time,datetime等
2.1import
一般常用在系统模块中
点语法:import 包名.模块名
调用函数:包名.模块名.函数名()
#注意:如果要跨文件调用其他文件中的函数或者访问变量,此时需要将其他的文件【模块】导入 #导入系统模块,同时导入多个模块,不同的模块之间的使用逗号隔开 import os,math,random #注意:导入自定义的模块,一定要注意模块的路径【相对路径】 #相对路径:必须找到一个参照物,参照物为当前的工程 import aaa.module import bbb.module #导入import:相当于将指定的文件加载了一遍 #调用函数 aaa.module.show() bbb.module.show() aaa.module.func2()
2.2from…import
一般使用在自定义模块中
pip:管理第三方模块的
安装:pip install xxx
卸载:pip uninstall xx
#from 包名.模块名 import 函数名或者变量名或者类名 #from aaa.module import show,func1 from aaa.module import * #将指定模块中的所有的内容【函数,变量,类】全部导入 #from bbb.module import show #from collections import Iterable #注意:如果采用from...import方式导入函数,如果两个模块中出现同名的函数,则后导入的函数会覆盖掉先导入的函数 def show(): print("hello") show() func1() print(num1)