#python中所有的迭代环境都会先尝试__iter__方法,在尝试__getitem__,只有在对象不支持迭代协议时,才会尝试索引
#迭代环境是通过调用内置函数iter去尝试寻找__iter__方法来实现的,而这种方法应该返回一个迭代器,如果已经提供了,python会重复调用这个迭代器对象的next方法,直到发生stopIteration异常,如果没有找到__iter__方法,python会改用__getitem__机制
class Squares:
def __init__(self, start, stop):
self.value=start-1
self.stop=stop
def __iter__(self):
return self
def __next__(self):
if self.value==self.stop:
raise StopIteration
self.value+=1
return self.value**2
s=Squares(1,1)
print(s) #<__main__.Squares object at 0x0000023291823F60>
print(iter(s)==s) #True s是个迭代器对象
for i in s:
print(i)
#print(next(s)) #builtins.StopIteration:
#print(s[1]) #迭代器没有重载索引表达式 builtins.TypeError: 'Squares' object does not support indexing
#__iter__只循环一次,而不是循环多次,每次新的循环都要创建一个新的迭代器
x=Squares(1,5)
print([n for n in x]) #[1, 4, 9, 16, 25]
print([n for n in x]) #[]
print([n for n in Squares(1,3)]) #[1, 4, 9]
print(list(Squares(1,3))) #[1, 4, 9]
#要达到多个迭代器的效果,__iter__只需替迭代器定义新的状态对象,而不是返回self
class SkipIterator:
def __init__(self, wrapped):
self.wrapped=wrapped
self.offset=0
def __next__(self):
if self.offset>=len(self.wrapped):
raise StopIteration
else:
item=self.wrapped[self.offset]
self.offset+=2
return item
class SkipObject:
def __init__(self, wrapped):
self.wrapped=wrapped
def __iter__(self):
return SkipIterator(self.wrapped)
a='abcdef'
s=SkipObject(a)
print(s) #<__main__.SkipObject object at 0x000001DEB47D4400>
#print(next(s)) #SkipObject没有定义__next__,builtins.TypeError: 'SkipObject' object is not an iterator
i=iter(s) #s是可迭代对象,返回一个迭代器i
print(i) #<__main__.SkipIterator object at 0x000001F2049EA1D0>
print(next(i), next(i), next(i)) #a c e
#print([x for x in i]) #i不支持迭代,builtins.TypeError: 'SkipIterator' object is not iterable
for x in s: #s不是一个迭代器,只是可以迭代的对象,因此每个循环都自己在字符串中的位置
for y in s:
print(x+y, end=', ') #aa, ac, ae, ca, cc, ce, ea, ec, ee,
print()
for x in 'ace':
for y in 'ace':
print(x+y, end=', ') #aa, ac, ae, ca, cc, ce, ea, ec, ee,
#这两种方式可以达到相同的结果,但是第二种是把列表整个存储在内存中,而迭代器是一次产生一个值,这样使得大型列表节省了实际的空间
#迭代环境是通过调用内置函数iter去尝试寻找__iter__方法来实现的,而这种方法应该返回一个迭代器,如果已经提供了,python会重复调用这个迭代器对象的next方法,直到发生stopIteration异常,如果没有找到__iter__方法,python会改用__getitem__机制
class Squares:
def __init__(self, start, stop):
self.value=start-1
self.stop=stop
def __iter__(self):
return self
def __next__(self):
if self.value==self.stop:
raise StopIteration
self.value+=1
return self.value**2
s=Squares(1,1)
print(s) #<__main__.Squares object at 0x0000023291823F60>
print(iter(s)==s) #True s是个迭代器对象
for i in s:
print(i)
#print(next(s)) #builtins.StopIteration:
#print(s[1]) #迭代器没有重载索引表达式 builtins.TypeError: 'Squares' object does not support indexing
#__iter__只循环一次,而不是循环多次,每次新的循环都要创建一个新的迭代器
x=Squares(1,5)
print([n for n in x]) #[1, 4, 9, 16, 25]
print([n for n in x]) #[]
print([n for n in Squares(1,3)]) #[1, 4, 9]
print(list(Squares(1,3))) #[1, 4, 9]
#要达到多个迭代器的效果,__iter__只需替迭代器定义新的状态对象,而不是返回self
class SkipIterator:
def __init__(self, wrapped):
self.wrapped=wrapped
self.offset=0
def __next__(self):
if self.offset>=len(self.wrapped):
raise StopIteration
else:
item=self.wrapped[self.offset]
self.offset+=2
return item
class SkipObject:
def __init__(self, wrapped):
self.wrapped=wrapped
def __iter__(self):
return SkipIterator(self.wrapped)
a='abcdef'
s=SkipObject(a)
print(s) #<__main__.SkipObject object at 0x000001DEB47D4400>
#print(next(s)) #SkipObject没有定义__next__,builtins.TypeError: 'SkipObject' object is not an iterator
i=iter(s) #s是可迭代对象,返回一个迭代器i
print(i) #<__main__.SkipIterator object at 0x000001F2049EA1D0>
print(next(i), next(i), next(i)) #a c e
#print([x for x in i]) #i不支持迭代,builtins.TypeError: 'SkipIterator' object is not iterable
for x in s: #s不是一个迭代器,只是可以迭代的对象,因此每个循环都自己在字符串中的位置
for y in s:
print(x+y, end=', ') #aa, ac, ae, ca, cc, ce, ea, ec, ee,
print()
for x in 'ace':
for y in 'ace':
print(x+y, end=', ') #aa, ac, ae, ca, cc, ce, ea, ec, ee,
#这两种方式可以达到相同的结果,但是第二种是把列表整个存储在内存中,而迭代器是一次产生一个值,这样使得大型列表节省了实际的空间