6 遍历操作
* 怎样让我们自己创建的对象可以使用for in 进行遍历?
+ 实现__getitem__方法
优先级低
- 每次for in 获取数据时, 都会调用这个方法
或者
+ 实现__iter__方法
优先级高
- 这个方法, 必须返回一个"迭代器";
"迭代器"即, 具备"__iter__"和"__next__"方法
当for in 遍历这个对象时, 会调用这个__iter__方法返回的迭代器对象的__next__方法
* 怎样让我们自己创建的对象可以使用 next() 函数进行访问?
实现__next__方法
补充
1. __iter__方法可以恢复迭代器的初始化值, 复用迭代器
2. "可迭代" 与 "迭代器"必须实现的方法
3. iter方法的使用
- 实现__getitem__方法
class Person:
def __init__(self):
self.result = 1
def __getitem__(self, item):
self.result += 1
if self.result >= 6:
raise StopIteration("停止遍历") #通过抛出异常结束遍历,否则会死循环
return self.result
p = Person()
for i in p:
print(i)
- 实现__iter__方法
__iter__
和__getitem__
方法同时实现,前者优先级高
# 返回迭代器 list
class Person:
def __init__(self):
self.result = 1
def __iter__(self):
print("iter")
self.result = 1
return iter([1, 2, 3, 4, 5]) #返回迭代器时,会调用迭代器内部的__next__方法
p = Person()
for i in p:
print(i)
# 不返回迭代器时,则会调用实例内部的 __next__ 方法
# 所以 iter 函数一般与 next 函数组合使用
class Person:
def __init__(self):
self.result = 1
def __iter__(self):
print("iter")
return self
def __next__(self):
self.result += 1
if self.result >= 6:
raise StopIteration("停止遍历")
return self.result
p = Person()
for i in p:
print(i)
- 验证迭代器所具备的条件
实现了__next__
方法不一定就是迭代器,迭代器必须要同时实现__iter__
和__next__
方法才行
import collections
class Person:
def __iter__(self):
pass
def __next__(self):
pass
p = Person()
print(isinstance(p, collections.Iterator)) # 是迭代器
print(isinstance(p, collections.Iterable)) # 也是可迭代对象,但是,可迭代对象只需要实现__iter__方法即可
对象 是 Iterable 一定能使用 for in
能使用for in 的对象不一定是 Iterable,因为只实现__getitem__
的也是可以执行 for in
- 通过
__iter__
初始化条件,让自定义迭代器重复使用
class Person:
def __init__(self):
self.age = 1
def __iter__(self):
self.age = 1
return self
def __next__(self):
self.age += 1
if self.age >= 6:
raise StopIteration("stop")
return self.age
p = Person()
for i in p:
print(i)
print("-" * 20)
for i in p:
print(i)
>>>> 打印结果
2
3
4
5
--------------------
2
3
4
5
- iter()函数的使用
- 将对象转化成迭代器
l = [1, 2, 3]
lt = iter(l)
print(lt)
>>> 打印结果
- 将实现getitem方法的自定义对象 转化成迭代器
class Person:
def __init__(self):
self.age = 1
def __getitem__(self, item):
self.age += 1
if self.age >= 6:
raise StopIteration("stop")
return self.age
p = Person()
print(p)
pt = iter(p)
print(pt)
print("-" * 20)
for i in pt:
print(i)
>>> 打印结果
<__main__.Person object at 0x107be8208>
--------------------
2
3
4
5
- 将自定义的迭代器对象(同时实现了iter 和 next,缺少一个都会报错) 转成 迭代器
class Person:
def __init__(self):
self.age = 1
def __iter__(self):
self.age = 1
return self
def __next__(self):
self.age += 1
if self.age >= 6:
raise StopIteration("stop")
return self.age
p = Person()
pt = iter(p) # 即使p 实例已经是迭代器,再通过 iter 转换是不会变的,即 pt = p
print(pt)
print(pt is p)
print("-" * 20)
for i in pt:
print(i)
>>> 打印结果
<__main__.Person object at 0x105462208>
True
--------------------
2
3
4
5
-
iter(x, y)第二个参数使用
# 当 x 为 callable 时 + __getitem__
class Person:
def __init__(self):
self.age = 1
def __getitem__(self, item):
self.age += 1
if self.age >= 6:
raise StopIteration("stop")
return self.age
p = Person()
pt = iter(p, 4)
for i in pt:
print(i)
>>> 打印结果
Traceback (most recent call last):
File "xxx", line xx, in
pt = iter(p, 4)
TypeError: iter(v, w): v must be callable
# 通过 iter(callable, sentinel)方式使用
class Person:
def __init__(self):
self.age = 1
def __call__(self, *args, **kwargs):
self.age += 1
if self.age >= 6:
raise StopIteration("stop")
return self.age
p = Person()
pt = iter(p, 4)
for i in pt:
print(i)
>>> 打印结果
2
3
# 也可以不实现 __call__
class Person:
def __init__(self):
self.age = 1
def __iter__(self):
self.age = 1
return self
def __next__(self):
self.age += 1
if self.age >= 6:
raise StopIteration("stop")
return self.age
p = Person()
pt = iter(p.__next__, 4)
for i in pt:
print(i)
>>> 打印结果
2
3