day4:迭代器、生成器、面向过程编程、三元表达式、列表推导式、生成器表达式、递归、匿名函数、内置函数
一、迭代器
1、迭代器概念:
迭代器就是迭代的工具,迭代是一个重复的过程,每次重复即一次迭代,并且每次迭代的结果都是下一次迭代的初始值
2、什么是可迭代对象?
可迭代对象指的是内置有__iter__方法的对象,即obj.__iter__,如下
'hello'.__iter__
(1,2,3).__iter__
[1,2,3].__iter__
{'a':1}.__iter__
{'a','b'}.__iter__
open('a.txt').__iter__
1 dic={ 2 'a':1, 3 'b':2, 4 'c':3 5 } 6 iter_dic=dic.__iter__() 7 print(iter_dic.__iter__() is iter_dic) 8 print(iter_dic.__next__()) 9 print(iter_dic.__next__()) 10 print(iter_dic.__next__())
1 iter_dic=dic.__iter__() 2 while 1: 3 try: 4 k=next(iter_dic) 5 print(dic[k]) 6 except StopIteration: 7 break
3、for循环的工作原理
#1:执行in后对象的dic.__iter__()方法,得到一个迭代器对象iter_dic
#2: 执行next(iter_dic),将得到的值赋值给k,然后执行循环体代码
#3: 重复过程2,直到捕捉到异常StopIteration,结束循环
4、迭代器的优缺点
#优点:
- 提供一种统一的、不依赖于索引的迭代方式
- 惰性计算,节省内存
#缺点:
- 无法获取长度(只有在next完毕才知道到底有几个值)
- 一次性的,只能往后走,不能往前退
二、生成器
只要函数内部包含有yield关键字,那么函数名()得到的结果就是生成器,并且不会执行函数内部代码
def func(): print('====>first') yield 1 print('====>second') yield 2 print('====>third') yield 3 print('====>end') g=func() print(g) #<generator object func at 0x0000000002184360>
生成器就是迭代器
1、练习
1)自定义函数模拟range(1,7,2)
2)模拟管道,实现功能:tail -f access.log | grep '404'
1. def range_test(x,y,z=1): while x <= y: yield x #print(x) x+=z g=range_test(1,2) print(next(g)) print(next(g)) 2. import time def 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.2) def grep(lines,partten): for line in lines: line=line.decode('utf-8') if partten in line: yield line for line in grep(tail('access.log'),'404'): print(line)
三、协成函数
#yield关键字的另外一种使用形式:表达式形式的yield def eater(name): print('%s 准备开始吃饭啦' %name) food_list=[] while True: food=yield food_list print('%s 吃了 %s' % (name,food)) food_list.append(food) g=eater('egon') g.send(None) #对于表达式形式的yield,在使用时,第一次必须传None,g.send(None)等同于next(g) g.send('蒸羊羔') g.send('蒸鹿茸') g.send('蒸熊掌') g.send('烧素鸭') g.close() g.send('烧素鹅') g.send('烧鹿尾')
def init(func): def inner(*args,**kwargs): g=func(*args,**kwargs) next(g) return g return inner @init def eater(name): print('%s begin eat!!!' %name) food_list=[] while True: food=yield food_list print('%s eat %s' %(name,food_list)) food_list.append(food) g=eater('egon') #g.send(None) #对于表达式形式的yield,在使用时,第一次必须传None,g.send(None)等同于next(g) g.send('蒸羊羔') g.send('蒸鹿茸') g.send('蒸熊掌') g.send('烧素鸭') g.send('烧素鹅') g.send('烧鹿尾')
import os def init(func): def wrapper(*args,**kwargs): g=func(*args,**kwargs) next(g) return g return wrapper @init def search(target): while True: filepath=yield g=os.walk(filepath) for dirname,_,files in g: for file in files: abs_path=r'%s\%s' %(dirname,file) target.send(abs_path) @init def opener(target): while True: abs_path=yield with open(abs_path,'rb') as f: target.send((f,abs_path)) @init def cat(target): while True: f,abs_path=yield for line in f: res=target.send((line,abs_path)) if res: break @init def grep(pattern,target): tag=False while True: line,abs_path=yield tag tag=False if pattern.encode('utf-8') in line: target.send(abs_path) tag=True @init def printer(): while True: abs_path=yield print(abs_path) g=search(opener(cat(grep('你好',printer())))) # g.send(r'E:\CMS\aaa\db') g=search(opener(cat(grep('python',printer())))) g.send(r'E:\CMS\aaa\db')
yield总结
#1、把函数做成迭代器
#2、对比return,可以返回多次值,可以挂起/保存函数的运行状态
四、三元表达式、列表推导式、生成器表达式
name=input('>>: ') res='sb' if name=='alex' else 'nb' print(res)
egg_list=['egg_%s' %i for i in range(10)] print(egg_list)
语法
[expression for item1 in iterable1 if condition1
for item2 in iterable2 if condition2
...
for itemN in iterableN if conditionN
]
egg_list=('egg_%s' %i for i in range(10)) print(egg_list) print(next(egg_list)) print(next(egg_list))
#1、把列表推导式的[]换成()就是生成器表达式
#2、示例:生一筐鸡蛋变成给你一只老母鸡,用的时候就下蛋,这也是生成器的特性
#3、优点:省内存,一次只产生一个值在内存中
list(chicken) #因chicken可迭代,因而可以转成列表
['鸡蛋1', '鸡蛋2', '鸡蛋3', '鸡蛋4',]
4.1 练习题
1、将names=['egon','alex_sb','wupeiqi','yuanhao']中的名字全部变大写
names=['egon','alex_sb','wupeiqi','yuanhao'] names=[i.upper() for i in names] print(names)
2、将names=['egon','alex_sb','wupeiqi','yuanhao']中以sb结尾的名字过滤掉,然后保存剩下的名字长度
names=['egon','alex_sb','wupeiqi','yuanhao'] names=[len(i) for i in names if not i.endswith('sb')] print(names)
3、求文件a.txt中最长的行的长度(长度按字符个数算,需要使用max函数)
with open('access.log','r',encoding='utf-8') as f: a=[len(i) for i in f] print(a) print(max(a))
4、求文件a.txt中总共包含的字符个数?思考为何在第一次之后的n次sum求和得到的结果为0?(需要使用sum函数)
with open('access.log', encoding='utf-8') as f: print(sum(len(i) for i in f))
5、思考题
with open('a.txt') as f: g=(len(line) for line in f) print(sum(g)) #为何报错?
因为print在with代码块之外,也就是相当于文件已经关闭,所以sum函数没有办法做运算
6、文件shopping.txt内容如下
mac,20000,3 lenovo,3000,10 tesla,1000000,10 chicken,200,1 求总共花了多少钱? 打印出所有商品的信息,格式为[{'name':'xxx','price':333,'count':3},...] 求单价大于10000的商品信息,格式同上
with open('shopping.txt') as f: info=[i.split(',')for i in f] cost=sum(int(x)*int(y) for _,x,y in info) print(cost) with open('shopping.txt') as f: info=[{ 'name':line.split(',')[0], 'price':line.split(',')[1], 'count':line.split(',')[2] } for line in f] with open('shopping.txt',encoding='utf-8') as f: info=[{ 'name': line.split()[0], 'price': float(line.split()[1]), 'count': int(line.split()[2]), } for line in f if float(line.split()[1]) > 10000] print(info)
---恢复内容结束---
一、迭代器
1、迭代器概念:
迭代器就是迭代的工具,迭代是一个重复的过程,每次重复即一次迭代,并且每次迭代的结果都是下一次迭代的初始值
2、什么是可迭代对象?
可迭代对象指的是内置有__iter__方法的对象,即obj.__iter__,如下
'hello'.__iter__
(1,2,3).__iter__
[1,2,3].__iter__
{'a':1}.__iter__
{'a','b'}.__iter__
open('a.txt').__iter__
1 dic={ 2 'a':1, 3 'b':2, 4 'c':3 5 } 6 iter_dic=dic.__iter__() 7 print(iter_dic.__iter__() is iter_dic) 8 print(iter_dic.__next__()) 9 print(iter_dic.__next__()) 10 print(iter_dic.__next__())
1 iter_dic=dic.__iter__() 2 while 1: 3 try: 4 k=next(iter_dic) 5 print(dic[k]) 6 except StopIteration: 7 break
3、for循环的工作原理
#1:执行in后对象的dic.__iter__()方法,得到一个迭代器对象iter_dic
#2: 执行next(iter_dic),将得到的值赋值给k,然后执行循环体代码
#3: 重复过程2,直到捕捉到异常StopIteration,结束循环
4、迭代器的优缺点
#优点:
- 提供一种统一的、不依赖于索引的迭代方式
- 惰性计算,节省内存
#缺点:
- 无法获取长度(只有在next完毕才知道到底有几个值)
- 一次性的,只能往后走,不能往前退
二、生成器
只要函数内部包含有yield关键字,那么函数名()得到的结果就是生成器,并且不会执行函数内部代码
def func(): print('====>first') yield 1 print('====>second') yield 2 print('====>third') yield 3 print('====>end') g=func() print(g) #<generator object func at 0x0000000002184360>
生成器就是迭代器
1、练习
1)自定义函数模拟range(1,7,2)
2)模拟管道,实现功能:tail -f access.log | grep '404'
1. def range_test(x,y,z=1): while x <= y: yield x #print(x) x+=z g=range_test(1,2) print(next(g)) print(next(g)) 2. import time def 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.2) def grep(lines,partten): for line in lines: line=line.decode('utf-8') if partten in line: yield line for line in grep(tail('access.log'),'404'): print(line)
三、协成函数
#yield关键字的另外一种使用形式:表达式形式的yield def eater(name): print('%s 准备开始吃饭啦' %name) food_list=[] while True: food=yield food_list print('%s 吃了 %s' % (name,food)) food_list.append(food) g=eater('egon') g.send(None) #对于表达式形式的yield,在使用时,第一次必须传None,g.send(None)等同于next(g) g.send('蒸羊羔') g.send('蒸鹿茸') g.send('蒸熊掌') g.send('烧素鸭') g.close() g.send('烧素鹅') g.send('烧鹿尾')
def init(func): def inner(*args,**kwargs): g=func(*args,**kwargs) next(g) return g return inner @init def eater(name): print('%s begin eat!!!' %name) food_list=[] while True: food=yield food_list print('%s eat %s' %(name,food_list)) food_list.append(food) g=eater('egon') #g.send(None) #对于表达式形式的yield,在使用时,第一次必须传None,g.send(None)等同于next(g) g.send('蒸羊羔') g.send('蒸鹿茸') g.send('蒸熊掌') g.send('烧素鸭') g.send('烧素鹅') g.send('烧鹿尾')
import os def init(func): def wrapper(*args,**kwargs): g=func(*args,**kwargs) next(g) return g return wrapper @init def search(target): while True: filepath=yield g=os.walk(filepath) for dirname,_,files in g: for file in files: abs_path=r'%s\%s' %(dirname,file) target.send(abs_path) @init def opener(target): while True: abs_path=yield with open(abs_path,'rb') as f: target.send((f,abs_path)) @init def cat(target): while True: f,abs_path=yield for line in f: res=target.send((line,abs_path)) if res: break @init def grep(pattern,target): tag=False while True: line,abs_path=yield tag tag=False if pattern.encode('utf-8') in line: target.send(abs_path) tag=True @init def printer(): while True: abs_path=yield print(abs_path) g=search(opener(cat(grep('你好',printer())))) # g.send(r'E:\CMS\aaa\db') g=search(opener(cat(grep('python',printer())))) g.send(r'E:\CMS\aaa\db')
yield总结
#1、把函数做成迭代器
#2、对比return,可以返回多次值,可以挂起/保存函数的运行状态
四、三元表达式、列表推导式、生成器表达式
name=input('>>: ') res='sb' if name=='alex' else 'nb' print(res)
egg_list=['egg_%s' %i for i in range(10)] print(egg_list)
语法
[expression for item1 in iterable1 if condition1
for item2 in iterable2 if condition2
...
for itemN in iterableN if conditionN
]
egg_list=('egg_%s' %i for i in range(10)) print(egg_list) print(next(egg_list)) print(next(egg_list))
#1、把列表推导式的[]换成()就是生成器表达式
#2、示例:生一筐鸡蛋变成给你一只老母鸡,用的时候就下蛋,这也是生成器的特性
#3、优点:省内存,一次只产生一个值在内存中
list(chicken) #因chicken可迭代,因而可以转成列表
['鸡蛋1', '鸡蛋2', '鸡蛋3', '鸡蛋4',]
4.1 练习题
1、将names=['egon','alex_sb','wupeiqi','yuanhao']中的名字全部变大写
names=['egon','alex_sb','wupeiqi','yuanhao'] names=[i.upper() for i in names] print(names)
2、将names=['egon','alex_sb','wupeiqi','yuanhao']中以sb结尾的名字过滤掉,然后保存剩下的名字长度
names=['egon','alex_sb','wupeiqi','yuanhao'] names=[len(i) for i in names if not i.endswith('sb')] print(names)
3、求文件a.txt中最长的行的长度(长度按字符个数算,需要使用max函数)
with open('access.log','r',encoding='utf-8') as f: a=[len(i) for i in f] print(a) print(max(a))
4、求文件a.txt中总共包含的字符个数?思考为何在第一次之后的n次sum求和得到的结果为0?(需要使用sum函数)
with open('access.log', encoding='utf-8') as f: print(sum(len(i) for i in f))
5、思考题
with open('a.txt') as f: g=(len(line) for line in f) print(sum(g)) #为何报错?
因为print在with代码块之外,也就是相当于文件已经关闭,所以sum函数没有办法做运算
6、文件shopping.txt内容如下
mac,20000,3 lenovo,3000,10 tesla,1000000,10 chicken,200,1 求总共花了多少钱? 打印出所有商品的信息,格式为[{'name':'xxx','price':333,'count':3},...] 求单价大于10000的商品信息,格式同上
with open('shopping.txt') as f: info=[i.split(',')for i in f] cost=sum(int(x)*int(y) for _,x,y in info) print(cost) with open('shopping.txt') as f: info=[{ 'name':line.split(',')[0], 'price':line.split(',')[1], 'count':line.split(',')[2] } for line in f] with open('shopping.txt',encoding='utf-8') as f: info=[{ 'name': line.split()[0], 'price': float(line.split()[1]), 'count': int(line.split()[2]), } for line in f if float(line.split()[1]) > 10000] print(info)
五、递归与二分法
1、递归调用的定义
#递归调用是函数嵌套调用的一种特殊形式,函数在调用时,直接或间接调用了自身,就是递归调用
2、递归示例
#图解。。。
# salary(5)=salary(4)+300
# salary(4)=salary(3)+300
# salary(3)=salary(2)+300
# salary(2)=salary(1)+300
# salary(1)=100
#
# salary(n)=salary(n-1)+300 n>1
# salary(1) =100 n=1
def salary(n):
if n == 1:
return 100
return salary(n-1)+300
print(salary(5))
3、修改递归最大深度
import sys
sys.getrecursionlimit()
sys.setrecursionlimit(2000)
n=1
def test():
global n
print(n)
n+=1
test()
test()
#虽然可以设置,但是因为不是尾递归,仍然要保存栈,内存大小一定,不可能无限递归
4、二分法
l=[1,2,10,30,33,99,101,200,301,402] print(l) a=int(input('>>: ')) while True: mid=len(l)//2 if a>l[mid]: l=l[mid+1:] elif a<l[mid]: l=l[:mid] else: print(l.index(a)) break
复制代码 l=[1,2,10,30,33,99,101,200,301,402] #从小到大排列的数字列表 def search(num,l): print(l) if len(l) > 0: mid=len(l)//2 if num > l[mid]: #in the right l=l[mid+1:] elif num < l[mid]: #in the left l=l[:mid] else: print('find it') return search(num,l) else: #如果值不存在,则列表切为空 print('not exists') return search(100,l)

浙公网安备 33010602011771号