一、迭代器

1、可循环的有哪些,即可用for语句或者while语句的数据类型有哪些?
  字符串(str)、列表(list)、元组(tuple)、字典(dic)、集合(set)、枚举类(enumerate)
  还有哪些非数据类型,但是可以循环的?
  range(10),   文件句柄:f = open('filename',mode='r',enconding='utf-8')
2、查看这些可循环的数据类型或者函数或者文件句柄
  都有哪些共同的东西:(求交集,想到集合(set)的操作了)。
  还要引入一个内置函数dir()
print(dir())
print(dir(' '))
  由返回结果可以看到,dir带参数时,返回该参数的属性、方法列表。
  不带参数时,返回当前范围内的变量、方法和定义的类型列表;
 # 先可以求list和str的交集方法了
str_method_li = set(dir(''))
list_method_li = set(dir([]))
res = str_method_li & list_method_li
print(res)
# 还是由很多共有的方法,加大力度
tuple_m_li = set(dir(()))
dic_m_li = set(dir({}))
range_m_li = set(dir(range(5)))
set_m_li = set(dir(set({1, 2, 3, 4})))
res = res & tuple_m_li & dic_m_li & range_m_li & set_m_li
print(res)
# 还是由很多,我们还是看一看交集中一个双下方法名:__iter__
# 补充说明一下“双下方法”:方法名中开头和结果都带有两个下滑线的,即叫双下方法!它是python中用C实现的方法!
# 这个__iter__, 跟可迭代对应的英文iterable很像!
我们可以得出结论:
只要是能被for循环的数据类型,就一定拥有__iter__方法!
print([].__iter__())
# 运行结果为:<list_iterator object at 0x000001C2AD37B4A8>
# 即得到list的迭代器对象,因此我们可以判断,该方法返回的是一个迭代器(iterator)!
iterator = 'lov'.__iter__()
print(dir(iterator))
# 看到迭代器中的方法中,有一个双下方法:__next__,我们来看看它得到的是什么?
print(iterator.__next__())
# 返回的是字符串中的第一字母,再执行一次!
print(iterator.__next__())
# 返回的是字符串中的第二字母,再执行一次!
print(iterator.__next__())
# 返回的是字符串中的第三字母,再执行一次!
#print(iterator.__next__()) # 报错 StopIteration
# 这说明迭代器可以一个一个取集合中的元素,只到没有时,抛出异常!
总结一下:
#Iterable 可迭代的 -- > __iter__ #只要含有__iter__方法的都是可迭代的
[].__iter__() 迭代器 -- > __next__ #通过next就可以从迭代器中一个一个的取值 延申一下:
只要含有__iter__方法的都是可迭代的 —— 可迭代协议
自定义一个类型,可以用来迭代
 from collections import Iterable
from collections import Iterator class A:
def __next__(self):pass
def __iter__(self):pass a = A()
print(isinstance(a, Iterable))
print(isinstance(a, Iterator))
结果都为True,说明该类即可被迭代,也是迭代器!
3、迭代器的概念
迭代器协议:内部含有__next__方法和__iter__方法的就是迭代器
小结一下:
迭代器协议和可迭代协议
可以被for循环的都是可迭代的
可迭代的内部都有__iter__方法
只要是迭代器 一定可迭代
可迭代的.__iter__()方法就可以得到一个迭代器
迭代器中的__next__()方法可以一个一个的获取值
我们可以推导一下, for循环其实就是在使用迭代器
  只有是可迭代对象的时候 才能用for
  当我们遇到一个新的变量,不确定能不能for循环的时候,就判断它是否可迭代
4、迭代器的好处
  从容器中一个一个取值,会将所有的值取到;
  节省内存空间:
 迭代器不会在内存中再占用一大块内存;
  每次next,都会给我们一个新的

二、生成器函数

1、生成器的引入场景

#如果想要一个包含2百万个ILOVEU的字符串,如何取得?如此取只会得到最后一个def func():
for i in range(2000000):
i = 'ILOVEU%s'%i
return i print(func())

改进一下:

def generate_str():
li = []
for i in range(200):
s = 'ILOVEU No' + str(i) + ' '
# print(s)
li.append(s)
return ','.join(li) print(generate_str())
如此做的确可以生成一个包含200万个’ILOVEU No%d‘的字符串,
但是如此使用迭代器无优势!因为它一次性在内存中生成,浪费内存空间,而迭代器的优点恰恰是节省内存!

总结:

理清迭代器的原理,可以理解for循环的是如何工作的,另外可以对了解生成器做铺垫!
迭代器虽然有很多优点,如节省内存空间,但是不能满足我们的所有需求;
如果我们平时在写代码过程中,要产生大量的数据,又不希望一次性在内存中生成,而且还要处处使用它,基于此种情况,
必须有我们自己写的迭代器!它就是生成器!

2、生成器有两种表现形式:

  1)、生成器函数 --- 本质上就是我们自己写的函数
  2)、生成器表达式

3、生成器函数的定义:

    只要含有yield关键字的函数都是生成器函数
 ef generator():
print(1)
#return 'a'
yield 'b' # yield不能和return共用且需要写在函数内 res = generator() # 生成器函数 : 执行之后会得到一个生成器作为返回值
print(res) # <generator object generator at 0x0000019C239AD4C0> def generator_full():
print(1)
yield 'a' # yield不会结束函数
print(2)
yield 'b'
yield 'c'
g = generator_full()
print(dir(g)) # 它有'__iter__' ret = g.__next__()
print(ret) # 执行步骤:1)执行g.__next__()双下函数;2)调用generator_full函数;3) print(1);4)执行:yield 'a' 返回a,但不退出函数,等待
ret = g.__next__()
print(ret)# 执行步骤:1)执行g.__next__()双下函数;2)调用generator_full函数;3) print(2); 4)yield 'b' 返回b,但不退出函数,等待
# ret = g.__next__()
# print(ret)# 执行步骤:1)执行g.__next__()双下函数;2)调用generator_full函数;3)yield 'c' 返回c,但不退出函数,等待
# ret = g.__next__()
# print(ret)# 执行步骤:1)执行g.__next__()双下函数;2)调用generator_full函数;3)发现没有yield,报错StopIteration for i in g: # 接着上面的继续迭代剩下的元素
print(i) # 用for循环迭代后,无法再迭代了!
# ret = g.__next__()
# print(ret)

4、使用生成器函数来生成200万个“ILOVEU No%d”

def s_generator():
for i in range(200):
yield 'ILOVEU No%d'%i s_g = s_generator()
# for i in s_g:
# print(i)

继续深入

 #需求:我要取出前50个ILOVEU
for i in range(50):
print(s_g.__next__()) i = 0
# 发现是按序号接着取元素,从ILOVEU No50开始取
while i < 50:
i += 1
print('----',s_g.__next__())
# 生成器与迭代器一样,会记录当前取到元素的位置,以及下一个元素的位置,随时都可以得到下一个元素! # 对比for循环列表(list,不是迭代器,但是可以迭代)
li = [2, 4, 6, 8, 10]
for i in li:
print(i)
if i == 6:
break for j in li:
print(j)
# 我们发现,没有从停止的位置的下一个位置取元素,而是重新取出所有元素!
# 原因不是list不是迭代器,for循环时,已经将其转换为迭代器,
# 而是,两次for的时候的迭代器不是同一个! #我们再来看生成器s_generator的例子
g1 = s_generator()
g2 = s_generator()
print(g1.__next__())
print(g2.__next__())
# 结果都是ILOVEU No0,说明同一个生成器(同时也是迭代器),__next__时才会记住元素位置

5、监听文件输入的内容,实时打印到命令行中

#普通方法:
def trip(file_path):
f = open(file_path, encoding='utf-8')
while 1:
line = f.readline() # 每次读一行
if line.strip():
print(line.strip()) # 缺点:不能返回line,如果return,循环就终止了 #trip('../day12_func/user_info') def monitor(file_path):
f = open(file_path, mode='r', encoding='utf-8')
while 1:
line = f.readline()
if line.strip():
yield line.strip() g = monitor('../day12_func/user_info')
for i in g:
if 'python' in i:
print('*****', i) ##修改文件后,按ctrl+s才能有效果!打印结果!

Python进阶-V 迭代器(Iterator)、生成器(Generator)函数的更多相关文章

  1. python 进阶篇 迭代器和生成器深入理解

    列表/元组/字典/集合都是容器.对于容器,可以很直观地想象成多个元素在一起的单元:而不同容器的区别,正是在于内部数据结构的实现方法. 所有的容器都是可迭代的(iterable).另外字符串也可以被迭代 ...

  2. Python进阶之迭代器和生成器

    可迭代对象 Python中任意的对象,只要它定义了可以返回一个迭代器的__iter__方法,或者定义了可以支持下标索引的__getitem__方法,那么它就是一个可迭代对象.简单来说,可迭代对象就是能 ...

  3. Python 闭包、迭代器、生成器、装饰器

    Python 闭包.迭代器.生成器.装饰器 一.闭包 闭包:闭包就是内层函数对外层函数局部变量的引用. def func(): a = "哈哈" def func2(): prin ...

  4. python设计模式之迭代器与生成器详解(五)

    前言 迭代器是设计模式中的一种行为模式,它提供一种方法顺序访问一个聚合对象中各个元素, 而又不需暴露该对象的内部表示.python提倡使用生成器,生成器也是迭代器的一种. 系列文章 python设计模 ...

  5. python is、==区别;with;gil;python中tuple和list的区别;Python 中的迭代器、生成器、装饰器

    1. is 比较的是两个实例对象是不是完全相同,它们是不是同一个对象,占用的内存地址是否相同 == 比较的是两个对象的内容是否相等 2. with语句时用于对try except finally 的优 ...

  6. Python语言的循环语句、迭代器与生成器、函数学习

    while循环语句 无限循环 我们可以通过设置条件表达式永远不为false来实现无限循环,实例如下: for语句 Python for循环可以遍历任何序列的项目,如一个列表或者一个字符串 Python ...

  7. 【python基础】迭代器和生成器函数

    1.迭代器协议: 1.迭代器协议是指:对象必须提供一个 __next__() 方法,执行该方法要么返回迭代中的下一项,要么就引起一个StopIteration异常,以终止迭代(只能往后走不能往前退) ...

  8. Python学习--07迭代器、生成器

    迭代 如果给定一个list或tuple,我们可以通过for循环来遍历这个list或tuple,这种遍历我们称为迭代(Iteration). Python里使用for...in来迭代. 常用可迭代对象有 ...

  9. Python学习笔记 - 迭代器Iterator

    我们已经知道,可以直接作用于for循环的数据类型有以下几种: 一类是集合数据类型,如list.tuple.dict.set.str等: 一类是generator,包括生成器和带yield的genera ...

随机推荐

  1. Codeforces Round #554 (Div. 2) D 贪心 + 记忆化搜索

    https://codeforces.com/contest/1152/problem/D 题意 给你一个n代表合法括号序列的长度一半,一颗有所有合法括号序列构成的字典树上,选择最大的边集,边集的边没 ...

  2. 【2019.7.22 NOIP模拟赛 T1】麦克斯韦妖(demon)(质因数分解+DP)

    暴力\(DP\) 先考虑暴力\(DP\)该怎么写. 因为每个序列之后是否能加上新的节点只与其结尾有关,因此我们设\(f_i\)为以\(i\)为结尾的最长序列长度. 每次枚举一个前置状态,判断是否合法之 ...

  3. Codeforces Round #597 (Div. 2) D. Shichikuji and Power Grid 最小生成树

    D. Shichikuji and Power Grid</centerD.> Shichikuji is the new resident deity of the South Blac ...

  4. AGC008E Next or Nextnext(组合计数,神奇思路)

    神仙题. 排列计数,一种常见的做法是 \(i\) 向 \(p_i\) 连边. 然而这里这个就逼迫我们只能从 \(i\) 向 \(a_i\) 连边. 不过没关系,考虑从 \(i\) 向 \(p_i\) ...

  5. linux 硬盘满了后,查看使用目录占用空间情况

    cd 切换到目录, du -ah --max-depth=1 查看当前目录下的 文件夹 占用情况

  6. 在Ubuntu18.04.2LTS上遇到的问题汇总

    在Ubuntu18.04.2LTS上遇到的问题汇总 一.前言   在新版的Ubuntu上在桌面右键没有新建文档的按钮着实让人难以接受,其实只要稍微理解就能明白设计者的良苦用心,因为这样便于扩展性和自定 ...

  7. vue+elementui+netcore混合开发

    1.VueController.cs using Bogus; using System; using System.Collections.Generic; using System.Linq; u ...

  8. SiIsEnterpriseFunctionsRestrictedOnOpenSource

    src/Cedar/Server.c SiIsEnterpriseFunctionsRestrictedOnOpenSource()

  9. python接口自动化3-发送post及其他请求

    前言 发过get请求相信学习post请求也很快学会,无非就是多了传参时的类型与参数格式.在我常见的post请求中用到最多的是json格式,但也有用其它,下面将介绍常用的参数类型格式. 一.Post请求 ...

  10. 一些优秀的 Entity Framework 开源项目

    增加全局过滤的项目(比如:IsDeleted 字段):https://github.com/zzzprojects/EntityFramework.DynamicFilters 谢谢浏览!