标签:分析 for循环 可迭代对象 部分 创建 none 方法 区分 特点
迭代对象: 在python中,但凡内部含有iter方法的对象,都是可迭代对象。
**迭代器: 在python中,内部含有__Iter__方法并且含有__next__方法的对象就是迭代器。**
可迭代对象 str
list
set
dic
python中规定,只要具有__ iter__()
方法就是可迭代对象
str.__iter__()# list.__iter__()# tuple.__iter__()# dict.__iter__()# set.__iter__()
将可迭代对象转换成迭代器
lis = lst.__iter__()
# print(lis.__next__()) # 下一位
# print(lis.__next__()) # 下一位
# print(lis.__next__()) # 下一位
# print(lis.__next__()) # 下一位
有多少元素就能next 多少次 超过范围报错
文件句柄就是一个迭代器 # f = open("usrinfo","a",encoding="utf-8")
while模拟for的内部循环机制
将可迭代对象转换成迭代器,然后利用next进行取值,最后利用异常处理处理StopIteration抛出的异常。
s = "alex"
s1 = s.__iter__()
while True:
try: # 尝试着运行一下缩进体中的代码
print(s1.__next__())
except StopIteration:
break
可迭代对象如何转化成迭代器,并且取值
方法一:
lst = [1,2,3,4]
l = lst.__iter__()
print(1.__next__()) #1
print(1.__next__()) #2
print(1.__next__()) #3
print(1.__next__()) #4
方法二
lst = [1,2,3,4]
l = iter(lst)
print(next(l)) #1
print(next(l)) #2
print(next(l)) #3
print(next(l)) #4 #推荐
python2 和python3
py2没有__iter__() 有iter()
py3 有__iter__() 有iter()
可迭代对象优点和缺点:
#优点
1.使用灵活(每个可迭代对象都有自己的方法)
2.能够直接查看元素的个数
#缺点
占内存
应用:内存空间大,当数据量比较少,建议使用可迭代对象
迭代器的优缺点及应用
#具有__iter__()和__next__()方法就是一个迭代器
#优点
节省内存
#缺点
1 只能向一个方向执行,不能退回
2 一次性的
3 不能灵活操作,不能直接看元素的个数
应用:当你的数据量过大,大到足以撑爆你的内存或者你以节省内存为首选因素时,将数据集设置为迭代器是一个不错的选择。(可参考为什么python把文件句柄设置成迭
代器)。
时间换空间:迭代器,生成器,用大量的时间来节省空间
空间换时间:可迭代对象,用大量空间来节省时间
lst = [1,2,3,4]
l = iter(lst)
#print(l) 输出结果是迭代器的内存地址 <list_iterator object at 0x0000018117F0BA58>
for i in l:# for循环可以直接去循环迭代器
print(i)
生成器的本质就是一个迭代器
最大的区别:
生成器的目的:不在通过数据转换实现,而是通过代码编写实现
生成器的定义:
1.基于函数实现的生成器
2.表达式实现生成器
这是一个函数
def func():
print(1)
return 5
print(func()) 这是一个函数
这是一个生成器
def func():
print(1)
yield 5
print(func()) 创建一个生成器对象 <generator object func at 0x0000025A8B022EB8>
表达式形式的生成器
gen = (i**2 for i in range(10))
print(next(gen))
博客推导式那里细讲
# def func():
# print(foo) 报错
# func()
# def func():
# print(foo) 不报错
因为计算机在查看代码时候会进行 1 语法分析 2词法分析 第一个是语法没有错,foo没有定义,但是他调用了,语法分析时没有问题,但是执行调用使用词法分析就
会报错
第二个虽然没定义foo 但是语法没有错误,词法错误,但是函数体没有调用,故不会报错
生成器怎么用:
特点:惰性机制
yield 和 return部分功能很像
def func( ):
yield 1 #记录执行位置的
yield 2
yield 3
g = func() #获取的是生成器的内存地址
print(next(g)) #1
print(next(g)) #2
print(next(g)) #3 惰性机制,不next 不往下执行
def func():
yield 1
yield 2
yield 3
g =func()
g1 =func()
g2= func()
print(g,g1,g2) 输出三个<generator object func at 0x00000133E5DA7990> 只不过后边的地址不一样,说明创建了三个生成器
def func():
yield
print(func().__next__()) NONE #得到是yield 返回的NONE
def func():
yield [1,2,3,4,5]
print(func().__next__(),type(func().__next__()))
得到的是[1,2,3,4,5] 类型是List
def func(): !!!!!这个有意思 结果是 1 NONE <class 'function'>
def foo():
print(1)
yield foo
g = func().__next__()
print(g(),type(g))
def func():
yield 1,2,3,4,5
print(123)
yield 111
g = func()
print(next(g))
print(next(g))
输出结果(1,2,3,4,5) 123 111 yield惰性 next往下走
yield from
def func():
yield [1,2,23,54,2] #将列表整体返回
yield from [1,2,23,54,5] #将列表中的元素逐个返回
g = func()
print(next(g)) [1,2,23,54,2]
print(next(g)) 1
print(next(g)) 2
print(next(g)) 23
print(next(g)) 54
print(next(g)) 5
总结:
在我理解就是生成器就是人造的迭代器,通过next取值,用时间换空间!
生成器一定是一个迭代器,但是迭代器不一定是一个生成器
迭代器和生成器的优点:
迭代器和生成器的缺点
1.不能直接使用元素
2.不能直观查看元素的个数
3.使用不灵活
4.稍微消耗时间
5.一次性的,不能逆行
当数据量特别大的时候,一定要记得用生成器
区分迭代器和生成器:
lst = [1,2,3]
print(lst.__iter__())
def func():
yield 1
print(func())
# 看内存地址 结果会显示iterator是迭代器 generator是生成器
yeild
return一般在函数中只设置一个,他的作用是终止函数,并且给函数的执行者返回值。
yield在生成器函数中可设置多个,他并不会终止函数,next会获取对应yield生成的元素。
yield 能返回多个,以元组的形式储存
yield 能返回各种数据类型
yield 能写多个并且都执行
yield 能够记录执行位置
yield 后边不写内容,默认返回NONE
yield from 是将数据逐个返回
可迭代对象:
具有__iter__()方法的就是一个可迭代对象
迭代器:
具有__iter__()和__next__()方法就是一个迭代器
生成器:
基于函数创建的生成器,函数体中必须存在yield
标签:分析 for循环 可迭代对象 部分 创建 none 方法 区分 特点
原文地址:https://www.cnblogs.com/zzsy/p/12219533.html