迭代器
迭代:迭代是一个重复的过程,每次重复即一次迭代,并且每次迭代的结果是下一次重复的初始值
l=['a','b','c'] count=0 while count < len(l): print(l[count]) count+=1
迭代器:迭代器即迭代的工具,它的作用是无论对于序列类型(如str,list,tuple),还是对于非序列类型(如dict,set,文件)等,都能获取其中的值
可迭代对象:内置有obj.__iter__方法的对象
迭代器对象:既内置有obj.__iter__方法,又内置有obj.__next__方法的对象,可迭代对象执行obj.__iter__方法后得到的就是迭代器对象
#可迭代的对象,obj.__iter__ l=[1,2,3] t=(1,2,3) d={'name':'luoli','age':18,'sex':'female'} s={'a','b','c'} f=open('user.txt','r',encoding='utf-8') l.__iter__() t.__iter__() d.__iter__() s.__iter__() f.__iter__() #迭代器对象:既有obj.__iter__,又有obj.__next__方法 f.__next__()
可迭代对象不一定是迭代器对象,迭代器对象一定是可迭代的对象;可迭代对象调用obj.__iter__方法得到的是迭代器对象,迭代器对象调用obj.__iter__方法得到的是本身
d={'name':'luoli','age':18,'sex':'female'} d_iter=d.__iter__() print(d_iter.__next__()) print(d_iter.__next__()) print(d_iter.__next__()) print(d_iter.__next__()) #迭代器取值完毕抛出异常
for循环详解
#调用in后的对象的iter方法,使其成为一个迭代器:obj_iter=obi.__iter__--->调用next方法获取值:k=obj_iter.__next__()--->捕捉异常,结束迭代 d={'name':'luoli','age':18,'sex':'female'} for k in d: print(k) d={'name':'luoli','age':18,'sex':'female'} d_iter=iter(d) while True: try: print(next(d_iter)) except StopIteration: break
迭代器优点:提供了一种统一的,不依赖于索引的取值方式,为for循环的实现提供了依据;更节省内存
缺点:只能往后并且一次性的取值;不能使用len()方法
生成器
只要函数内部包括yield关键字,那么函数名()得到的结果就是生成器,并且不会执行函数内部代码
生成器就是迭代器,yield提供了一种自定义迭代器的方法
yield与return的区别:yield可以返回多次值;函数暂停与继续的状态由yield保存
def func(): print('--1') yield 1 print('--2') yield 2 print('--3') yield 3 #调用生成器函数将返回一个生成器 g=func() #第一次调用生成器的next方法时,生成器才开始执行生成器函数(而不是构建生成器时),直到遇到yield时暂停执行(挂起),并且yield的参数将作为此次next方法的返回值 next(g) #之后每次调用生成器的next方法,生成器将从上次暂停执行的位置恢复执行生成器函数,直到再次遇到yield时暂停,并且同样的,yield的参数将作为next方法的返回值 next(g) next(g) #如果当调用next方法时生成器函数结束(遇到空的return语句或是到达函数末尾),则这次next方法的调用将抛出StopIteration异常(即for循环终止的条件) next(g)
yield表达式形式的用法
def eater(name): print('%s ready to eat'%name) food_list=[] while True: food=yield food_list #food=yield=banana food_list.append(food) print('%s start eat to eat %s'%(name,food)) print(food_list) e=eater('luoli') #首先要初始化 next(e) #e.send(None) #然后传值e.send()从暂停的位置将值传给yield,然后功能与next一样 e.send('banana') e.send('peach')
练习
(1)自定义函数模拟range()
def my_range(start,stop,step=1): while start < stop: yield start start+=step g=my_range(1,500,2) print(next(g)) print(next(g)) print(next(g))
(2)模拟管道,实现功能:tail -f access.log | grep '404'
import time def tail(filepath): with open(filepath,'rb') as f: f.seek(0,2) while True: line=f.readline() if line: yield line else: time.sleep(2) print('run') def grep(lines,pattern): for line in lines: line=line.decode('utf-8') if pattern in line: yield line lines=grep(tail('access.log'),'404') for line in lines: print (line)
三元表达式
def my_max(x,y): if x>y: return x else: return y x=20 y=30 res=x if x>y else y
列表推导式
l=['egg'+str(i) for i in range(1,11) if i>=6] print(l)
生成器表达式
g=('egg'+str(i) for i in range(1,1000000000000)) print(g) print(next(g)) print(next(g)) print(next(g))
# 练习 # 将names=['egon','alex_sb','wupeiqi','yuanhao']中的名字全部变大写 names=['egon','alex_sb','wupeiqi','yuanhao'] names=[name.upper() for name in names] print(names) # 将names中以sb结尾的名字过滤掉,然后保存剩下的名字长度 names=[name for name in names if name.endswith('sb')] print(names) # 求文件a.txt中最长的行的长度(长度按字符个数算,需要使用max函数) with open('a.txt','r',encoding='utf-8') as f: # l=[] # for line in f: # #print(len(line)) # l.append(len(line)) res=max(len(line) for line in f) print(res) # 求文件a.txt中总共包含的字符个数?思考为何在第一次之后的n次sum求和得到的结果为0?(需要使用sum函数) with open('a.txt','r',encoding='utf-8') as f: res=sum(len(line) for line in f) print(res)
递归
递归调用:在调用一个函数的过程中,直接或者间接调用该函数本身,称之为递归调用
递归的两个阶段:1.递推 2.回溯
def func(n): print('--->',n) func(n+1) func(0) import sys print(sys.getrecursionlimit()) #查看递归深度 sys.setrecursionlimit(2000) #修改递归最大深度
def age(n): if n == 1: return 18 return age(n-1) + 2 res=age(5) print(res)
l=[1,[2,[3,[4,[5,[6,[7,]]]]]]] def func(l): for item in l: if type(item) is list: func(item) else: print(item) func(l)
二分法
#实现类似l(num)的功能 l=[1,2,30,45,57,68,78,93,100] #从小到大排列的数字列表 def binary_search(l,num): print(l) if len(l) == 0: print('not exist') return mid_index=len(l)//2 if num >l[mid_index]: binary_search(l[mid_index+1:],num) elif num < l[mid_index]: binary_search(l[0:mid_index],num) else: print('find it') binary_search(l,688) #实现类似l(num,index)的功能 l=[1,2,10,20,30,55,67,87,92,102,293,304] def search(num,l,start=0,stop=len(l)-1): if start <= stop: mid=start+(stop-start)//2 print('start:[%s] stop:[%s] mid:[%s] mid_vla:[%s]'%(start,stop,mid,l[mid])) if num > l[mid]: start=mid+1 elif num <l[mid]: stop=mid-1 else: print('find it',mid) return search(num,l,start,stop) else: print('not exist') return search(30,l)
匿名函数
lambda x,y:x+y
#应用 s='hello' l=[1,2,3] g=zip(s,l) print(list(g)) salaries={ 'lary':3000, 'jone':100000000, 'tom':10000, 'jerry':2000 } #zip/max/min/sorted/ g=zip(salaries.values(),salaries.keys()) print(max(g)) print(max(salaries,key=lambda k:salaries[k])) print(min(salaries,key=lambda k:salaries[k])) print(sorted(salaries,key=lambda k:salaries[k])) print(sorted(salaries,key=lambda k:salaries[k],reverse=True)) #map names=['lary','jone','tom','lily'] print(list(map(lambda name:"%s_01"%name,names))) #filter names=['lary_01', 'jone_01', 'tom_01', 'lily'] g=filter(lambda x:x.endswith('01'),names) print(list(g)) from functools import reduce print(reduce(lambda x,y:x+y,range(1,101),100))
内置函数
查看内置函数:https://docs.python.org/3/library/functions.html?highlight=built