活动地址:CSDN21天学习挑战赛
学习的最大理由是想摆脱平庸,早一天就多一份人生的精彩;迟一天就多一天平庸的困扰。各位小伙伴,如果您:
想系统/深入学习某技术知识点…
一个人摸索学习很难坚持,想组团高效学习…
想写博客但无从下手,急需写作干货注入能量…
热爱写作,愿意让自己成为更好的人
目录
一、迭代器
01.迭代器
a.什么是迭代?
迭代是访问集合元素的一种方式。迭代器是一个可以记住遍历的位置的对象。迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束。迭代器只能往前不会后退。
b.举列
如:我们说数据类型里面可以迭代的即可以用for循环遍历--->元组 列表 字符串......
c.判断依据
如何判断一个类型是否可以迭代?
from collections.abc import Iterable isinstance([11, 22], Iterable) # 判断其与Iterable之间是否归属关系,如果返回True则可迭代
补充isinstance()是一个判断如isinstance(1, int)判断1和int之间是否有归属关系
d.自己创建一个可迭代对象
想法:想实现一个类,在外面给类加属性,然后通过for循环遍历所加的元素。
思路:
1.创建一个可以被for循环而不会报错的可迭代对象
from collections.abc import Iterable
import time
class Classmate(object):
def __init__(self):
self.names = list()
def add(self, name):
self.names.append(name)
def __iter__(self):
"""如果想要一个对象称为一个可迭代对象,即可以实现for,那么必须实现__iter__方法"""
return ClassIterator() # 返回一个具有__inter__方法和__next__方法的对象的引用
class ClassIterator(object):
def __iter__(self):
pass
def __next__(self):
return 11
classmate = Classmate()
classmate.add("老王")
classmate.add("王二")
classmate.add("李四")
classmate.add("张三")
print("判断对象classmate是否是可迭代对象:", isinstance(classmate, Iterable))
for name in classmate:
print(name)
time.sleep(1)
结果:
知识储备:
如果想实现
for i in xx_obj:
pass
条件:
1.判断xx_obj对象是否可以迭代,在类里面定义__iter__使其可以迭代,同时注意方法里面要有返回值。判断方法isinstance(xx_obj, Iterable)
2.在第一步成立的条件下调用__iter__函数-->__iter__(xx_obj)
(循环遍历时会自动调用__iter__方法)得到xx_obj对象的__iter__方法的返回值即:一个对象的引用(返回值的这个对象里面有__iter__方法和__next__方法)我们称这个个对象为迭代器
3.__iter__方法的返回值是一个迭代器(即一个有__iter__方法和__next__方法的对象)
4.for循环就是通过迭代器里面的__next__函数来取值,调用一次取一次(调用一次给i一次)
分析上面代码以及原因:
2.如果一直返回11这一个固定的值有啥意思如何实现返回我添加到类里面的数据?
from collections.abc import Iterable
import time
class Classmate(object):
def __init__(self):
self.names = list()
def add(self, name):
self.names.append(name)
def __iter__(self):
"""如果想要一个对象称为一个可迭代对象,即可以实现for,那么必须实现__iter__方法"""
return ClassIterator(self) # 把自己的引用传递给这个对象
class ClassIterator(object):
def __init__(self, obj):
self.obj = obj
def __iter__(self):
pass
def __next__(self):
return self.obj.names[0]
classmate = Classmate()
classmate.add("老王")
classmate.add("王二")
classmate.add("李四")
classmate.add("张三")
print("判断对象classmate是否是可迭代对象:", isinstance(classmate, Iterable))
for name in classmate:
print(name)
time.sleep(1)
分析:
总结: 因为通过第一个类把自身引用当成参数传入第二个类,而第二个类通过此参数对第一个类的值进行访问,从而实现了打印第一个类添加的属性的值。
3.一直打印类属性里面的一个也不是办法怎么打印添加到类里面的全部呢?
import time
class Classmate(object):
def __init__(self):
self.names = list()
def add(self, name):
self.names.append(name)
def __iter__(self):
"""如果想要一个对象称为一个可迭代对象,即可以实现for,那么必须实现__iter__方法"""
return ClassIterator(self) # 把自己的引用传递给这个对象
class ClassIterator(object):
def __init__(self, obj):
self.obj = obj
self.count = 0
def __iter__(self):
pass
def __next__(self):
ret = self.obj.names[self.count]
self.count += 1
return ret
classmate = Classmate()
classmate.add("老王")
classmate.add("王二")
classmate.add("李四")
classmate.add("张三")
for name in classmate:
print(name)
time.sleep(1)
4.如何使其取完 了值就自动关闭程序而不报错呢?
import time
class Classmate(object):
def __init__(self):
self.names = list()
def add(self, name):
self.names.append(name)
def __iter__(self):
"""如果想要一个对象称为一个可迭代对象,即可以实现for,那么必须实现__iter__方法"""
return ClassIterator(self) # 把自己的引用传递给这个对象
class ClassIterator(object):
def __init__(self, obj):
self.obj = obj
self.count = 0
def __iter__(self):
pass
def __next__(self):
if self.count < len(self.obj.names):
ret = self.obj.names[self.count]
self.count += 1
return ret
# 怎么告诉迭代器取完了
else:
raise StopIteration # 抛出这个异常会使迭代器自动停止
classmate = Classmate()
classmate.add("老王")
classmate.add("王二")
classmate.add("李四")
classmate.add("张三")
for name in classmate:
print(name)
time.sleep(1)
解析:
5.每次定义两个类有时候挺麻烦的怎么办?
import time
class Classmate(object):
def __init__(self):
self.names = list()
self.count = 0
def add(self, name):
self.names.append(name)
def __iter__(self):
"""如果想要一个对象称为一个可迭代对象,即可以实现for,那么必须实现__iter__方法"""
return self # 把自己的引用传递给这个对象
def __next__(self):
if self.count < len(self.names):
ret = self.names[self.count]
self.count += 1
return ret
else:
raise StopIteration
classmate = Classmate()
classmate.add("老王")
classmate.add("王二")
classmate.add("李四")
classmate.add("张三")
for name in classmate:
print(name)
time.sleep(1)
解析:
前面已经讨论了想实现
for i in xx_obj:
pass
的条件:
1.判断xx_obj对象是否可以迭代,在类里面定义__iter__使其可以迭代,同时注意方法里面要有返回值。判断方法isinstance(xx_obj, Iterable)
2.在第一步成立的条件下调用__iter__函数-->__iter__(xx_obj)
(循环遍历时会自动调用__iter__方法)得到xx_obj对象的__iter__方法的返回值即:一个对象的引用(返回值的这个对象里面有__iter__方法和__next__方法)我们称这个个对象为迭代器
3.__iter__方法的返回值是一个迭代器(即一个有__iter__方法和__next__方法的对象)
4.for循环就是通过迭代器里面的__next__函数来取值,调用一次取一次(调用一次给i一次)那么我可以第一个类里面定义__iter__方法和__next__方法,然后第一个类返回本身(因为本身也符合条件)
e.迭代器的应用-斐波那契数列
打印前十一个斐波那契数列的两个方式
nums = list()
a = 0
b = 1
nums.append(a)
for i in range(10):
a, b = b, a+b # (1, 0+1)
nums.append(a)
for num in nums:
print(num)
class Fibonacci(object):
def __init__(self, all_num):
self.count_num = 0
self.all_num = all_num
self.a = 0
self.b = 1
def __iter__(self):
"""如果想要一个对象称为一个可迭代对象,即可以实现for,那么必须实现__iter__方法"""
return self # 把自己的引用传递给这个对象
def __next__(self):
if self.count_num < self.all_num:
ret = self.a
self.a, self.b = self.b, self.a+self.b
self.count_num += 1
return ret
else:
raise StopIteration
fibo = Fibonacci(10)
for num in fibo:
print(num)
对比:
第一段代码
第二段代码
可以看出第二段代码只是存储生成斐波那契数列的方式,生成了一个就直接输出而并没有存储斐波那契数列值。但是第一段代码则是先存储了斐波那契数列的值再进行输出。
故使用了迭代器使运行代码使内存使用更少了。
二、总结
很明显协程都还没提到过讲了一大段关于迭代器的知识,这样做会使你更加了解协程,明天将更新生成器等知识。希望今天我分享部分知识你看懂了,明天咱们继续加油。
追寻光,成为光,发散光的路途肯定充满了坎坷,希望咱们一起撑住这段努力的岁月,最后一起品尝成功的果实,散发出自己的光芒。