可迭代对象
- str,tuple,dict,list,set,bytes都为可迭代对象
- range的结果是一个 range 对象,是一个可迭代对象
- 可迭代对象的本质:
- 在迭代一个可迭代对象的时候,实际上就是先获取该对象提供的一个迭代器,然后通过这个迭代器来依次获取对象中的每一个数据。
- 那么也就是说,一个具备了_ _iter _ _方法的对象,就是一个可迭代对象。
迭代器
-
python中只要实现了
__iter__
和__next__
方法的对象都可以称之为迭代器, -
_ _iter _ _() 方法返回一个特殊的迭代器对象,迭代器的 _ _ iter _ _() 返回⾃身, 这个迭代器对象实现了 _ _next _ _() 方法返回下一个值并通过 StopIteration 异常标识迭代的完成。
-
迭代器是一个带状态的对象,可以记录迭代的位置。
-
str / bytes / list / tuple / dict / set ⾃身不是迭代器,他 们⾃身不具备 _ _next _ _() , 但是具有 _ _iter _ _() , _ _iter _ _() ⽅法 ⽤来把⾃身转换成⼀个迭代器
-
In [1]: s='asdfghh' #字符串为可迭代对象 In [2]: si=s.__iter__() #调用__iter__()方法返回一个迭代器 In [3]: next(si) Out[3]: 'a'
-
_ _next _ _() 方法(Python 2 里是 next())会返回下一个迭代器对象。
-
执行顺序:
class A:
def __init__(self):
self.count=10
def __iter__(self):
print('执行 __iter__')
return self
def __next__(self):
print('执行 __next__')
if self.count>0:
self.count-=1
return self.count
else:
print('停止迭代')
raise StopIteration
for i in A():
print('i=',i)
#################################打印的结果
'''
执行 __iter__ #先执行__iter__,返回一个可迭代对象
执行 __next__
i= 9
.
.
.
执行 __next__
i= 1
执行 __next__
i= 0
执行 __next__
停止迭代
'''
- 练习:用迭代器实现斐波那契数列
class FibonaccIterator(object):
def __init__(self,n):
self.n=n
self.current=0
self.num1=1
self.num2=1
def __iter__(self):
return self
def __next__(self):
if self.current < self.n:
x=self.num1
self.num1,self.num2=self.num2,self.num1+self.num2
self.current +=1
return x
else:
raise StopIteration
生成器
-
generator: ⽣成器是⼀种特殊的迭代器, 不需要⾃定义 _ _iter _ _ 和 _ _next _ _
-
对一个函数使用yield关键字进行值得返回
-
生成器能自己记录当前的运行状态,下次启动时会从上次的位置继续执行
-
yield 语句执行时,生成器对象会让出解释器的控制权,生成器自身会挂起
def foo():
print(111)
yield 222 #yield会让出解释器的控制权,挂起
print(333)
yield 444
print(555)
n=foo() #含有yield就是一个特殊的函数,仅仅是在封装一个生成器对象
#并不会执行任何结果
next(n)#只有next调用才会有结果
x = next(n) # 打印 111,返回 222
y = next(n) # 打印 333,返回 444
z = next(n) # 打印 555,抛出 异常
-
除了使用yield实现生成器外,还有另外一种方法实现生成器
-
In [1]: x=(i for i in range(10)) In [2]: type(x) Out[2]: generator
-
-
练习:使用生成器实现斐波那契数列
def gen_fib(n):
num1=num2=1
current=0
while current < n:
yield num1
num1,num2=num2,num1+num2
current+=1
F=gen_fib(12)
for i in F:
print(i)
手写一个range
class Range:
def __init__(self, start, end=None, step=1):
if end is None:
self.start = 0
self.end = start
else:
self.start = start
self.end = end
self.step = step
def __iter__(self):
return self
def __next__(self):
if self.start < self.end:
current = self.start
self.start += self.step
return current
else:
raise StopIteration
for i in Range(5):
print(i)
for i in Range(5, 10):
print(i)
for i in Range(10, 20, 3):
print(i)
使用迭代器,生成器的好处
- 节省内存
- 可使用 sys标准库中的getsizeof方法查看使用内存的大小
In [4]: x=range(10000)
In [5]: y=[i for i in range(10000)] #列表推导式
In [6]: import sys
In [7]: sys.getsizeof(x)
Out[7]: 48
In [8]: sys.getsizeof(y)
Out[8]: 87624
- 惰性求值 (惰性求值思想来⾃于 Lisp 语⾔)
来源:CSDN
作者:半岛囚天
链接:https://blog.csdn.net/qq_40313877/article/details/104440974