python中有一个内置的函数iter,相信所有都知道它的用法,就是传入一个可迭代对象得到一个迭代器。
lst = [1, 2, 3]
print(iter(lst)) # <list_iterator object at 0x00000217100D4E50>
print(iter(lst).__next__()) # 1
但这只是iter的第一个用法,你知道它的第二个用法吗?iter还可以接收一个可调用对象和一个value,iter(callable, value)
,然后会不断地调用callable,直到返回的值等于value的时候终止迭代。我们举例说明:
i = iter(str, "abc")
print(i) # <callable_iterator object at 0x0000027447BA4E50>
# 直接打印是一个迭代器,但如果使用for循环对i进行遍历的话会得到什么结果呢?
# 答案是会无限循环,我们说会不断地调用callable,直到返回的值等于value
# 而调用str返回的是一个空字符串,而空字符串不等于"abc", 因此会一直调用
for idx, _ in enumerate(i):
if idx > 4:
break
print("%r" % _)
"""
''
''
''
''
''
"""
# 我们当前只打印5次,如果是for _ in i:的话,那么会无限循环
lst = [11, 22, 33, 44, 55]
for _ in iter(iter(lst).__next__, 44):
print(_)
"""
11
22
33
"""
# 再比如
def foo():
yield "a"
yield "b"
yield "c"
yield "d"
for _ in iter(foo().__next__, "c"):
print(_)
"""
a
b
"""
需要注意的是:对于
iter(foo().__next__, "c")
来说,相当于f = foo();iter(f.__next__, "c")
,并不是每次都重新执行一次foo(),这一点需要注意。同理,对于iter(iter(lst).__next__, 44)
也是如此。
这种方式可以用在socket通信中,当然文件的读取也可以,只不过文件读取的话没必要使用这种方式,不过就用文件读取来演示一下吧
from functools import partial
data = b""
f = open("1.txt", "rb")
# 每次读取3个字节
reader = partial(f.read, 3)
# 不停地调用reader,直到内容读取完毕,再次读取返回空字节的时候,结束循环
for _ in iter(reader, b""):
data += _
print(data.decode("utf-8")) # 那一日,人们终于回想起被巨人支配的恐惧