算法学python——python中的iterable和iterator

106 阅读2分钟

题目

www.marscode.cn/practice/65…

image.png

方法一

def solution(n: int) -> list:
    ans = []
    i = 1
    while i <= n:
        for ele in range(n, i - 1, -1):
            ans.append(ele)

        i += 1
    return ans

方法二

def solution(n: int) -> list:
    result = []
    for i in range(1, n + 1):
        # 生成从n到i的逆序子数组
        sub_array = list(range(n, i - 1, -1))
        # 将子数组拼接到结果中
        result.extend(sub_array)
    return result

学习:

作为前端开发,用惯了JS,最近深受python语法简洁性的吸引。方法一是正常的写法,但python中的list方法可以接受一个range对象直接生成数组,于是有了方法二。

让我们深入探究其原理:list(range(n, i - 1, -1))

python中的iterable(可迭代对象)

image.png

进入list的类型,我们发现list进行初始化时,可以传入一个iterable对象。

注意:那为什么list(x)里,xiterable而不是self呢,self是什么?self其实就相当于js class的方法中的this,只不过在js类的方法中this不需要作为形参显式声明。而在python中第一个形参必须要写self(虽然可以用其他命名,但self是约定俗成的命名)

回到iterablejs中也有可迭代对象,在js中,可迭代对象会具有[Symbol.iterator]属性,这个属性是一个方法,用于返回一个迭代器(iterator),js中只要一个对象实现了next()方法,那我们就称它为迭代器(所以可以用鸭子模型来判断是否是迭代器)。

想必python中也有类似的判断,让我们看向range对象:

image.png

由上图可见,range对象有startstopstep属性,还有function variablesspecial variables。 在special variables中,我们可以找到__iter__属性,相当于js中的[Symbol.iterator]

image.png

__iter__是一个方法,用于返回一个迭代器,python中的迭代器是指实现了__next__方法的对象:

image.png

所以list接收到这个range对象,对调用它的迭代器来生成一个列表。

python中列表的extend方法

再进入list的类型,可以看到extend方法也接收一个iterable,执行时会调用这个迭代器将元素逐一添加到末尾。比循环数组每一项挨个append简洁很多:

[1, 2, 3].extend[4, 5]  // [1, 2, 3, 4, 5]