解包和打包,iterator & iteratable

148 阅读1分钟

解包和打包的对象是可迭代对象:

解包

模拟解包过程

def unpack_example(iterable):
    it = iter(iterable)  # 获取迭代器
    a = next(it)         # 获取第一个元素
    b = next(it)         # 获取第二个元素
    c = list(it)         # 获取剩余的所有元素
    return a, b, c

result = unpack_example([1, 2, 3, 4, 5])
print(result)  # 输出: (1, 2, [3, 4, 5])

直接解包

a, b, c = [1, 2, 3]

*捕获剩余元素

a, *_, c = [1, 2, 3, 4]

循环中的解包

pairs = [(1, 'one'), (2, 'two'), (3, 'three')]
for num, word in pairs:
    print(num, word)

打包

zip 函数将多个可迭代对象作为参数,返回一个元组iterator,每个元组包含来自所有输入可迭代对象的相应元素。(注意:每一个iterator都需要实现__iter__()函数,所以每一个iterator都是一个iterable,所以这里的zip之后的结果虽然是iterator,但仍然可以使用for loop来访问。)

a = [1, 2, 3]
b = ['one', 'two', 'three']
c = [4.0, 5.0, 6.0]
print(zip(a, b, c))
print(*zip(a, b, c))
# <zip object at 0x106ff1140>
# (1, 'one', 4.0) (2, 'two', 5.0) (3, 'three', 6.0)

这里*zip(a, b, c)的返回结果是对iterator解包,iterator中的每个元素都会被取出,直到iterator耗尽。

zip等价函数

def zip(*iterables):
    iterators = [iter(it) for it in iterables]
    while iterators:
        result = []
        for it in iterators:
            try:
                result.append(next(it))
            except StopIteration:
                return
        yield tuple(result)

这里函数的参数是*iterables,这表明会将接受对象整合为一个元组。 我们传入的参数也是一系列的对象,可以通过对iterator解包来实现这一点。

l = range(5)
zip(*l)

iterable

iterable是一个形容词,描述实现了__iter__方法的对象,使用__iter__方法可以得到一个iterator

每一个生成器,也就是generator object,都是iterable

x = (i for i in range(3))
# x=<generator object <genexpr> at 0x1065dec20>