题目
方法一
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(可迭代对象)
进入list的类型,我们发现list进行初始化时,可以传入一个iterable对象。
注意:那为什么
list(x)里,x是iterable而不是self呢,self是什么?self其实就相当于jsclass的方法中的this,只不过在js类的方法中this不需要作为形参显式声明。而在python中第一个形参必须要写self(虽然可以用其他命名,但self是约定俗成的命名)
回到iterable,js中也有可迭代对象,在js中,可迭代对象会具有[Symbol.iterator]属性,这个属性是一个方法,用于返回一个迭代器(iterator),js中只要一个对象实现了next()方法,那我们就称它为迭代器(所以可以用鸭子模型来判断是否是迭代器)。
想必python中也有类似的判断,让我们看向range对象:
由上图可见,range对象有start、stop、step属性,还有function variables和special variables。
在special variables中,我们可以找到__iter__属性,相当于js中的[Symbol.iterator]:
__iter__是一个方法,用于返回一个迭代器,python中的迭代器是指实现了__next__方法的对象:
所以list接收到这个range对象,对调用它的迭代器来生成一个列表。
python中列表的extend方法
再进入list的类型,可以看到extend方法也接收一个iterable,执行时会调用这个迭代器将元素逐一添加到末尾。比循环数组每一项挨个append简洁很多:
[1, 2, 3].extend[4, 5] // [1, 2, 3, 4, 5]