一 迭代器
一 迭代的概念
迭代器即迭代的工具, 那什么是迭代呢?
迭代是一个重复的过程, 每次重复即一次迭代, 并且每次迭代的结果都是下一次迭代的初始值
- while True: #只是单纯地重复, 因而不是迭代
- print(===>)
- l=[1,2,3]
- count=0
- while count <len(l): #迭代
- print(l[count])
- count+=1
二 为何要有迭代器? 什么是可迭代对象? 什么是迭代器对象?
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__()
3 什么是迭代器对象?
可迭代对象执行 obj.__iter__()得到的结果就是迭代器对象,
而迭代器对象指的是即内置有__iter__()又内置有__next__()方法的对象
文件类型是迭代器对象 open(
- a.txt
- ).
- __iter__
- () open(
- a.txt).__next__()
- #hello.__iter__()
- #(1,2,3).__iter__()
- #[1,2,3].__iter__()
- #{a:1}.__iter__()
- #{a,b}.__iter__()
- #open(a.txt).__iter__()
- open(a.txt).__iter__()
- open(a.txt).__next__() #我们发现只有文件是迭代器对象
4 注意: 迭代器对象一定是可迭代对象, 而可迭代对象不一定是迭代器对象
三 迭代器对象的使用
- dic={a:1,b:2,c:3}
- iter_dic=dic.__iter__() #得到迭代器对象, 迭代器对象即有__iter__()又有__next__(), 但是: 迭代器.__iter__()得到的仍然是迭代器本身
- iter_dic.__iter__() is iter_dic #True
- print(iter_dic.__next__()) #等同于 next(iter_dic)
- print(iter_dic.__next__()) #等同于 next(iter_dic)
- print(iter_dic.__next__()) #等同于 next(iter_dic)
- # print(iter_dic.__next__()) #抛出异常 StopIteration, 或者说结束标志
- # 有了迭代器, 我们就可以不依赖索引迭代取值了
- iter_dic=dic.__iter__()
- while 1: #布尔值不是 0, 空, None False 别的都是 Ture
- try:
- k=next(iter_dic)
- print(dic[k])
- except StopIteration:
- break
- # 这么写太 low 了, 还需要我们自己捕捉异常, 控制 next,
python 这么牛逼, 肯定有简洁模式! 请看 for 循环
四 for 循环
- # 基于 for 循环, 我们可以完全不再依赖索引去取值了
- dic={a:1,b:2,c:3}
- for line in dic:
- print(dic[line])
- # for 循环原理分析:
- #1for 循环称之为迭代器循环, in 后跟的必须是可迭代的对象
- #2for 循环会执行 in 后对象的__iter__方法, 拿到迭代器对象
- #3 然后调用迭代器对象的__next__方法, 拿到一个返回值赋值给 line, 执行一次循环体
- #4 周而复始, 直到取值完毕, for 循环会检测到异常自动结束循环
五 迭代器的优缺点
优点:
1 提供一种统一的不依赖于索引的取值方式
2 惰性计算, 节省内存
缺点:
1 取值麻烦, 只能一个一个取, 只能往后走
2 一次性的, 不能往前退无法获取长度(只有在 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>
二 生成器就是迭代器
- def func():
- print(====>first)
- yield 1
- print(====>second)
- yield 2
- print(====>third)
- yield 3
- print(====>end)
- g=func()
- g.__iter__
- g.__next__
- # 上面所讲的同时有__iter__()和__next()方法, 就是迭代器
- # 所以生成器就是迭代器, 因此可以这么取值
- res=next(g)
- print(res) #一次 next()执行一次 yield
三 练习
自定义函数模拟 range(1,7,2)
- def my_range(start,stop,step=1):
- while start <stop:
- yield start
- start+=step
- # 执行函数得到生成器, 本质就是迭代器
- obj=my_range(1,7,2) #1 3 5
- print(next(obj))
- print(next(obj))
- print(next(obj))
- print(next(obj)) #StopIteration
- # 应用于 for 循环
- for i in my_range(1,7,2):
- print(i)
四 yield 总结
1 为我们提供了一种自定义迭代器的方式,
可以在函数内用 yield 关键字, 调用函数拿到的结果就是一个生成器, 生成器就是迭代器
2yield 可以像 return 一样用于返回值, 区别是 return 只能返回一次值, 而 yield 可返回多次
因为 yield 可以保存函数执行的状态
三面向过程编程
1 首先强调: 面向过程编程绝对不是用函数编程这么简单, 面向过程是一种编程思路思想, 而编程思路是不依赖于具体的语言或语法的
言外之意是即使我们不依赖于函数, 也可以基于面向过程的思想编写程序
2 定义: 面向过程的核心是过程二字, 过程指的是解决问题的步骤, 即先干什么再干什么 基于面向过程设计程序就好比在设计一条流水线, 是一种机械式的思维方式
3 优点: 复杂的问题流程化, 进而简单化
4 缺点: 可扩展性差, 修改流水线的任意一个阶段, 都会牵一发而动全身
5 应用: 扩展性要求不高的场景, 典型案例如 linux 内核, git,httpd
6 举例 流水线 1: 用户输入用户名密码 --->用户验证 --->欢迎界面
ps: 函数的参数传入, 是函数吃进去的食物, 而函数 return 的返回值, 是函数拉出来的结果
面向过程的思路就是, 把程序的执行当做一串首尾相连的功能, 该功能可以是函数的形式, 然后一个函数吃, 拉出的东西给另外一个函数吃,
吃完再拉, 拉完再吃, 人生就是吃拉睡
来源: http://www.bubuko.com/infodetail-2544873.html