可迭代对象
迭代器用到两个魔法方法__iter__和__next__
# 有很多可迭代对象: list/tuple/dict/set/str/range/filter/map
# for...in后面加可迭代对象
from collections.abc import Iterable
# 自己仿照list/str等来写一个可迭代对象
class Demo(object):
count = 0
def __init__(self,x):
self.x = x
def __iter__(self): # 1.只要一个类重写了__iter__方法就是一个可迭代对象
return self # 2.返回自己,之后再调用__next__方法,并且__next__调用结束后__iter__会继续不断调用
def __next__(self):
self.count += 1
if self.count <= self.x:
return self.count - 1
else:
raise StopIteration # 3.除非__next__让迭代器停止,才会停止迭代
d = Demo(10)
# isinstance用来判断一个实例对象是否是有指定的类创建出来的
print(isinstance(d, Iterable)) # True
# for...in循环的本质就是调用可迭代对象__iter__方法,获取到这个方法的返回值
# 这个返回值需要是一个对象,然后再调用这个对象__next__方法
for x in d: # d就是我们自己写了一个range(1,10)
print(x)
# 0
# 1
# 2
# 3
# 4
# 5
# 6
# 7
# 8
# 9
判断数据是否是可迭代对象
from collections.abc import Iterable
# for...in循环后面需要的是一个可迭代对象
for x in 'hello': # 字符串是可迭代对象
print(x)
# for y in 10: # 数字不是可迭代对象
# print(y)
a = 'hi'
b = ['婷婷','明明','佳佳','坤坤','琳琳','黎黎','梦凡','瑶瑶']
c = ('yes','good','ok')
d = {1,2,3,4,5,6}
person = {'名字':'张三','年龄':18}
nums = range(0,10)
for 甲 in person:
print(person[甲])
print('-' * 20)
print(isinstance(a, Iterable)) # True
print(isinstance(b, Iterable)) # True
print(isinstance(c, Iterable)) # True
print(isinstance(d, Iterable)) # True
print(isinstance(person, Iterable)) # True
print(isinstance(nums, Iterable)) # True
手动迭代
# 可迭代对象并不是继承自Iterable 类,而是对象重写了__iter__方法
from collections.abc import Iterable
class Person(object):
def __init__(self,name):
self.name = name
self.count = 0
def __iter__(self):
return self # 类重写了__iter__方法狗需要返回一个可迭代对象,可以直接返回它自己,因为他自己就是一个可迭代对象
# 返回它自己就会调用它自己的__next__方法,所以我们需要重写__next方法
def __next__(self):
if self.count < self.name:
self.count +=1
return self.count - 1
else:
raise StopIteration # 停止迭代
p = Person(10)
# 手动迭代:
print(p.__iter__().__next__()) # 0
print(p.__iter__().__next__()) # 1
print(p.__iter__().__next__()) # 2
print(p.__iter__().__next__()) # 3
print(p.__iter__().__next__()) # 4
# 等价于上面的代码:
# print(next(iter(p))) # 0
# print(next(iter(p))) # 1
# print(next(iter(p))) # 2
# print(next(iter(p))) # 3
# print(next(iter(p))) # 4
我们手动写个range对象
class MyRange(object):
def __init__(self,x):
self.x = x
self.y = 0
def __iter__(self):
return self
def __next__(self):
if self.y < self.x:
self.y +=1
return self.y - 1
else:
raise StopIteration
mr = MyRange(10)
for x in mr:
print(x) # 1 2 3 4 5 6 7 8 9
# 进阶版:取10-100范围,支持步进
class 取范围(object):
def __init__(self, 甲, *甲_长度可变参数):
self.甲 = 甲
self.乙 = 1
self.index = 0
if len(甲_长度可变参数) == 1:
self.甲 = 甲_长度可变参数[0]
self.index = 甲
elif len(甲_长度可变参数) == 2:
self.甲 = 甲_长度可变参数[0]
self.乙 = 甲_长度可变参数[1]
self.index = 甲
def __iter__(self):
return self
def __next__(self):
if self.index < self.甲 :
self.index += self.乙
return self.index - self.乙
else :
raise StopIteration
丙 = 取范围(10,55)
for 丁 in 丙:
print(丁)
迭代器和列表的区别
# 1.列表会申请一块内存空间,用来保存1~1000000 的数字
nums = [i for i in range(1000000)]
print(nums) # 这100万个数据存在列表中,特别占内存
# 2.迭代器不会开辟内存空间保存数据
for 甲 in range(1000000):
print(甲) # 随用随取
# 硬件固定的前提下:时间换空间,空间换时间