迭代器:迭代的工具
#1 什么是迭代:指的是一个重复的过程,每一次重复称为一次迭代,并且每一次重复的结果是下一次重复的初始值
#2 为什么要有迭代器?
#对于序列类型:str,list,tuple,可以依赖索引来迭代取值,
#但是对于dict,set,文件,python必须为我们提供一种不依赖于索引的迭代取值的方式-》迭代器
#3 可迭代的对象(下列都是):obj.iter
name='egon'l=[1,2,3]t=(1,2,3)d={'name':'egon','age':18,'sex':'male'}s={'a','b','c'}f=open('a.txt','w',encoding='utf-8')name.__iter__l.__iter__t.__iter__d.__iter__s.__iter__f.__iter__
#4 迭代器对象(文件是):obj.iter,obj.next
f.__iter__f.__next__
#总结:
#1 可迭代对象不一定是迭代器对象
#2 迭代器对象一定是可迭代的对象
#3 调用obj.iter()方法,得到的是迭代器对象(对于迭代器对象,执行iter得到的仍然是它本身)
#for循环就是依赖的将可迭代对象转换为迭代器对象,然后进行迭代
#总结迭代器的优缺点:
#优点:
#1、提供一种统一的、不依赖于索引的取值方式,为for循环的实现提供了依据
#2、迭代器同一时间在内存中只有一个值——》更节省内存,
#缺点:
#1、只能往后取,并且是一次性的
#2、不能统计值的个数,即长度
l=[1,2,3,4,5,6]l[0]l[1]l[2]l[0]l_iter=l.__iter__()# print(l_iter)print(next(l_iter))print(next(l_iter))print(next(l_iter))
生成器
#1 什么是生成器:只要在函数体内出现yield关键字,那么再执行函数就不会执行函数代码,会得到一个结果,该结果就是生成器
#生成器就是迭代器
#yield的功能:
#1、yield为我们提供了一种自定义迭代器对象的方法
#2、yield与return的区别1:yield可以返回多次值 #2:函数暂停与再继续的状态是由yield帮我们保存的
#模拟tail -f access.log |grep 404
import timedef tail(file): with open(file,'rb') as f: f.seek(0,2) while True: line = f.readline() if line: yield line else: time.sleep(0.05)lines=tail('access.log')def grep(lines,pattern): for line in lines: line = line.decode('utf-8') if pattern in line: print(line)grep(tail('access.log'),'404')
#了解知识点:yield表达式形式的用法
def eater(name): print('%s 开始吃饭' %name) food_list=[] while True: food=yield food_list #food=yield='鸡丁' food_list.append(food) print('%s start to eat %s' %(name,food))e=eater('dzm')#需要先初始化next(e)#然后e.send:1 从暂停的位置将值传给yield 2、与next一样print(e.send('米饭'))print(e.send('鸡丁'))
三元表达式
def my_max(x,y): if x > y: return x else: return yres=my_max(10,20)print(res)
#示例一
x=10y=20res=x if x > y else yprint(res)
#示例二
name=input('>>: ').strip()res='sb' if name == 'alex' else 'nb'print(res)
列表推导式
#示例一
l=[]for i in range(1,11): res='egg'+str(i) l.append(res)print(l)l=['egg'+str(i) for i in range(1,11)]print(l)
#示例二
l1=['egg'+str(i) for i in range(1,11) if i >= 6]print(l1)l1=[]for i in range(1,11): if i >= 6: l1.append('egg'+str(i))
生成器表达式
#把列表推导式的[]换成()就是生成器表达式
#生成器比较节省内存
g=('egg'+str(i) for i in range(0,1000000000000000000000000000000000))print(g) #显示结果g是个生成器print(next(g))print(next(g))print(next(g))
#示例with open('a.txt','r',encoding='utf-8') as f:
#求文件a.txt中最长的行的长度(长度按字符个数算,需要使用max函数)print(max(len(line)for line in f))
#求文件a.txt中总共包含的字符个数print(sum(len(line) for line in f))
递归
#递归调用:在调用一个函数的过程中,直接或者间接又调用该函数本身,称之为递归调用
#递归必备的两个阶段:1、递推 2、回溯
#python中的递归效率低,需要在进入下一次递归时保留当前的状态,在其他语言中可以有解决方法:尾递归优化,即在函数的最后一步(而非最后一行)调用自己,但是python又没有尾递归,且对递归层级做了限制
#举例,计算age(5)的数值
# age(5) = age(4) + 2# age(4) = age(3) + 2# age(3) = age(2) + 2# age(2) = age(1) + 2## age(1) = 18def func(n): if n == 1: return 18 else: return func(n-1)+2res=func(5)print(res)
#总结递归的使用:
#1. 必须有一个明确的结束条件
#2. 每次进入更深一层递归时,问题规模相比上次递归都应有所减少
#3. 递归效率不高,递归层次过多会导致栈溢出(在计算机中,函数调用是通过栈(stack)这种数据结构实现的,每当进入一个函数调用,栈就会加一层栈帧,每当函数返回,栈就会减一层栈帧。由于栈的大小不是无限的,所以,递归调用的次数过多,会导致栈溢出)
二分法
#了解的知识点
l=[1,2,10,30,33,99,101,200,301,402] #从小到大排列的数字列表,找到301
def search(l,num): print(l) if len(l) == 0: print('没有这个内容') return mid_index = len(l) // 2 if num > l[mid_index]: search(l[mid_index+1:],num) elif num < l[mid_index]: search(l[0:mid_index],num) else: print(num)x=int(input('请输入数字: '))search(l,x)
匿名函数
def func(): #func=内存地址 print('from func')func()
#上面这是有名函数
#举例
#内存地址
def my_sum(x,y): return x+y
#把上面有名函数变为匿名函数
#自带return返回值效果print(lambda x,y:x+y)
#打印后得到一个内存地址
#给这个内存地址传参执行print((lambda x,y:x+y)(1,2))
#得到3
#也可以:
func=lambda x,y:x+y#print(func)print(func(1,2))
#lambda匿名函数通常跟别的函数配合使用
#匿名意味着引用计数为0,使用一次就释放,除非让其有名字
内置函数(与匿名函数配合使用)
#max,min,sorted,map,reduce,filter
#上面的函数都遵循迭代器对象
#next一次取一次值
#字典的运算:最小值,最大值,排序
salaries={ 'egon':3000, 'alex':100000000, 'wupeiqi':10000, 'yuanhao':2000}
#zip 拉链
s='hello'l=[1,2,3]g=zip(s,l)
#g是一个内存地址
#zip的结果是一个迭代器
print(list(g))#结果[('h', 1), ('e', 2), ('l', 3)]
#使用列表形式表现出来,从结果可以看出一一对应的保存在一个小元祖中
#max函数
#举例,求上面字典中工资最高的人名
#方法1,可以和上面的zip函数配合g=zip(salaries.values(),salaries.keys())
#这样就可以按照薪资value比较,字典默认按照keys比较print(max(g))
#结果(100000000, 'alex')
#方法2,与匿名函数配合print(max(salaries,key=lambda x:salaries[x]))
#结果:alex
#'key='表示指定max函数比较的依据
#'k'是前面每次循环salaries后得到的字典的key,salaries[k]的结果返回给前面的key
#也就是说这里使用字典中的value进行比较,但显示的还是比较后结果所对应的字典中的key
#min函数
#用法跟max相同print(min(salaries,key=lambda k:salaries[k]))
#sorted 排序
#与max用法相同print(sorted(salaries,key=lambda k:salaries[k]))
#还可以加个reverse=True将结果反转print(sorted(salaries,key=lambda k:salaries[k],reverse=True))
#map,reduce,filter
#map 映射
#举例说明:
#将列表中的字符串后面都加上_SB
names=['alex','wupeiqi','yuanhao']l=[]for name in names: res='s%_SB' %name l.append(res)print(l)
#使用map函数实现
g=map(lambda name:'%s_SB' %name,names)print(list(g))
#结果:['alex_SB', 'wupeiqi_SB', 'yuanhao_SB']
#filter 过滤
names=['alex_SB', 'wupeiqi_SB', 'yuanhao_SB','egon']g=filter(lambda x:x.endswith('SB'),names)print(list(g))
#结果:['alex_SB', 'wupeiqi_SB', 'yuanhao_SB']
#reduce 合并
from functools import reduceprint(reduce(lambda x,y:x+y,range(1,101)))
#结果
5050print(reduce(lambda x,y:x+y,range(1,101),100))
#结果5150
#最后的100是初始值,原本初始值是1,现在改为100
内置函数
#需要掌握
#divmod 得到商和余
print(divmod(10001,25))(400, 1)
#只要余不为0就需要加1
#enumerate
#对于一个可迭代的(iterable)/可遍历的对象(如列表、字符串),enumerate将其组成一个索引序列,利用它可以同时获得索引和值
#enumerate多用于在for循环中得到计数
l=['a','b','c']for i,v in enumerate(l): print(i,v)
#结果:
0 a1 b2 c
#enumerate还可以接收第二个参数,用于指定索引起始值,如:
list1 = ["这", "是", "一个", "测试"]for index, item in enumerate(list1, 1): print(index, item)
#结果:
1 这
2 是
3 一个
4 测试
#补充
#如果要统计文件的行数,可以这样写:
#利用enumerate():
count = 0for index, line in enumerate(open(filepath,'r')): count += 1
#eval
#将字符串str当成有效的表达式来求值并返回计算结果
#将字符串转成相应的对象,转换成列表,转换成字典,转换成元组等
res=eval('[1,2,3]')print(res,type(res))
#结果:[1, 2, 3] <class 'list'>
#pow
res=pow(2,3,3) #2的三次方的结果对3取余print(res)
#结果:2
#round 四舍五入
print(round(3.5))4
#slice 切片
#制造一个切片格式
l=['a','b','c','d','e','f']s=slice(1,5,2)print(l[s])
#结果:['b', 'd']
共同学习,写下你的评论
评论加载中...
作者其他优质文章