列表

列表对象 list 是高级数据结构的一种,通过方括号括起、逗号分隔的一组值得到。类型是 list。

type([1,2,3])
list

列表是可变序列,通常用于存放同类项目的集合。但没做限制,可以存放任意对象。

[1,'a',int]
[1, 'a', int]

列表是可变的,分别创建两个值相同的列表,一定是不同的对象;而同一个列表对象中的元素是可以改变的:

a, b = [1,2], [1,2]
a == b
True
id(a), id(b)
(2004948061384, 2004947934152)
a[0] = 'a'
a, id(a)
(['a', 2], 2004948061384)

列表创建方法有:直接用一对方括号表示;列表推导式;或使用内建函数 list()

[], [1,2]
([], [1, 2])
[i for i in range(3)]
[0, 1, 2]
list('abc')
['a', 'b', 'c']

列表的所有切片都将得到一个新列表,这意味着以下切片操作会返回列表的一个浅拷贝:

list_1 = [1,2,3]
list_2 = list_1[:]
id(list_1), id(list_2)
(2004947038600, 2004948064968)

然而,列表可以利用切片改变自身的内容,列表仍然是原来的列表:

list_1[:] = 'abc'
list_1, id(list_1)
(['a', 'b', 'c'], 2004947038600)

列表推导式

列表推导式提供了一个更简单的创建列表的方法。常见的用法是把某种操作应用于序列或可迭代对象的每个元素上,然后使用其结果来创建列表,或者通过满足某些特定条件元素来创建子序列。

对比下列两种创建数值平方列表的方式:

squares = []
for x in range(5):
    squares.append(x**2)

print(squares)
print(x) # 产生了一个变量 x 
[0, 1, 4, 9, 16]
4
squares = [y**2 for y in range(5)]
print(squares)
print(y) # 没有多余变量 y
[0, 1, 4, 9, 16]


---------------------------------------------------------------------------

NameError                                 Traceback (most recent call last)

<ipython-input-3-c81791cbad54> in <module>
      1 squares = [y**2 for y in range(5)]
      2 print(squares)
----> 3 print(y) #


NameError: name 'y' is not defined

我们发现,列表推导式简洁漂亮、易读,不会产生多余的变量而可能带来副作用。

列表推导式示例:

 [(x, y) for x in [1,2] for y in [1,3] if x != y]
[(1, 3), (2, 1), (2, 3)]

相当于:

_list = []
for x in [1,2]:
    for y in [1,3]:
        if x != y:
            _list.append((x,y))
_list
[(1, 3), (2, 1), (2, 3)]

列表推导式可以使用复杂的表达式和嵌套函数:

from math import pi
[str(round(pi, i)) for i in range(1, 4)]
['3.1', '3.14', '3.142']

嵌套的列表推导式:

matrix = [[1, 2, 3],
          [5, 6, 7]]
[[row[i] for row in matrix] for i in range(3)]
[[1, 5], [2, 6], [3, 7]]

相当于:

matrix = [[1, 2, 3],
          [5, 6, 7]]
_list = []
for i in range(3):
    lst = []
    for row in matrix:
        lst.append(row[i])
    _list.append(lst)
_list
[[1, 5], [2, 6], [3, 7]]

判断语句在前的列表推导式:

[True if i % 2 == 0 else False for i in [1,4,7,9]]
[False, True, False, False]

相当于:

_list = []
for i in [1,4,7,9]:
    if i % 2 == 0:
        _list.append(True)
    else:
        _list.append(False)
_list
[False, True, False, False]

列表的索引和切片

列表是序列类型中的可变类型,它的索引和切片操作,和通用的序列操作比较,有许多不一样的地方,主要体现在利用索引和切片对列表元素进行增、删、改。

索引和切片是序列类型通用操作,详细的规则和用法,见序列索引和切片

列表可以利用索引替换某一个元素:

_list = [1,2,3]
_list[1] = 0
_list
[1, 0, 3]

利用切片将切片中的元素替换为可迭代对象中的元素:

_list = [1,2,3]
_list[1:3] = '123'
_list
[1, '1', '2', '3']
# 该替换,切片长度和可迭代对象长度必须相等
_list = [1,2,3,4,5]
_list[1:5:2] = '24'
_list
[1, '2', 3, '4', 5]

需要注意,替换并没有改变原来的列表对象:

list_1 = [1,2,3]
print(id(list_1),list_1)
list_1[2] = 0
print(id(list_1),list_1)
list_1[:] = range(5)
print(id(list_1),list_1)
list_1[::2] = ('a','b','c')
print(id(list_1),list_1)
2065281773704 [1, 2, 3]
2065281773704 [1, 2, 0]
2065281773704 [0, 1, 2, 3, 4]
2065281773704 ['a', 1, 'b', 3, 'c']

可以利用切片在列表中任意位置插入数据片段:

_list = [1,2,3]
# 在前面插入两个 0
_list[:0] = (0,0)
print(_list)
# 在索引为 2 的元素前面插入 'a','b'
_list[2:2] = ['a','b']
_list
[0, 0, 1, 2, 3]


[0, 0, 'a', 'b', 1, 2, 3]

列由切片浅拷贝列表,生成新的列表,但列表中有可变对象时,新列表中的可变对象和对应的原来列表中的可变对象是同一个对象的多次引用:

list_1 = [[1,2],3,4]
list_2 = list_1[:]
print('原列表:',id(list_1),'新列表:',id(list_2))
print('原列表中的可变对象:',
      id(list_1[0]),
      '\n新列表中对应的可变对象:',id(list_2[0]))
原列表: 2065281774536 新列表: 2065281774664
原列表中的可变对象: 2065281383112 
新列表中对应的可变对象: 2065281383112

改变其中一个,都会跟着改变。需要注意区分修改列表中元素的元素,和修改列表元素的区别:

list_1[0][0] = 'a'
print(list_1, list_2)
list_1[0] = 'a'
print(list_1, list_2)
[['a', 2], 3, 4] [['a', 2], 3, 4]
['a', 3, 4] [['a', 2], 3, 4]

list.clear 删除所有元素

列表方法 list.clear(),Python 官方文档描述如下:

help(list.clear)
Help on method_descriptor:

clear(self, /)
    Remove all items from list.

删除列表中所有的元素。相当于 del a[:](a 是列表)。

_list = [1,2,3]
_list.clear()
_list
[]

del a[:] 是删除列表 a 中的所有元素,和 a 的浅拷贝无关:

a = [1,2,3]
b = a[:]
del a[:]
a, b
([], [1, 2, 3])

该方法是一个过程 (过程就是不返回有意义结果的函数;在 Python 中,过程的返回值为 None), 直接对原列表进行修改:

_list = [1,2,3]
a = _list.clear()
print(a)
None

列表操作符

列表可以使用 比较运算符,但比较运算符对数据通用,单独用一个知识点讲解。该知识点介绍有列表自己特性的操作符 +*

操作符 +

操作符 +,可以让两个列表元素顺序不变地合并到一个新的列表中:

list_1 = [1,2]
list_2 = [3,4]
list_1 + list_2, list_2 + list_1
([1, 2, 3, 4], [3, 4, 1, 2])

操作符 + 还可以与赋值操作符 = 连用,将一个列表中的元素,加到另一个列表中(相当于 list.extend()),而不创建一个新列表:

list_1 = [1,2]
list_2 = [3,4]
print(id(list_1))
list_1 += list_2
id(list_1), list_1
2893532728008


(2893532728008, [1, 2, 3, 4])

操作符 *

操作符 *,可以将列表中的元素重复 n 次,得到一个新列表:

list_1 = [1,2]
list_2 = list_1*2
print(id(list_1),id(list_2))
list_2
2893532600136 2893532727432


[1, 2, 1, 2]

**注意:**如果列表中有可变对象,重复 n 次后,可变对象是同一个对象的多次引用,改变一个,都会跟着改变。

list_1 = [[0]]
list_2 = list_1*3
print(list_2)
list_1[0][0] = 1
list_2
[[0], [0], [0]]


[[1], [1], [1]]

操作符 *,还可以与赋值操作符 = 连用,用一个列表的元素重复 n 次来扩充它自身,而不创建新列表:

_list = [1,2]
print(id(_list))
_list *= 2
id(_list), _list
2893532727624


(2893532727624, [1, 2, 1, 2])

当 n 小于 1 时,则得到空列表:

[1,2,3]*0
[]

列表是可迭代对象,* 可以将列表拆包:

print(*[1,2,3])
1 2 3

list.append 添加一个元素

列表方法 list.append(),Python 官方文档描述如下:

help(list.append)
Help on method_descriptor:

append(self, object, /)
    Append object to the end of the list.

在列表的末尾添加一个元素。相当于 a[len(a):] = [x](a 是一个列表)。添加的元素可以是任何对象。

_list = [1,2]
_list.append('abc')
_list.append(list.append)
_list
[1, 2, 'abc', <method 'append' of 'list' objects>]

该方法是一个过程 (过程就是不返回有意义结果的函数;在 Python 中,过程的返回值为 None), 直接对原列表进行修改:

_list = []
a = _list.append('')
print(a)
None

list.extend 加入可迭代对象中元素

列表方法 list.extend(),Python 官方文档描述如下:

help(list.extend)
Help on method_descriptor:

extend(self, iterable, /)
    Extend list by appending elements from the iterable.

使用可迭代对象中的所有元素来扩展列表。相当于 a[len(a):] = iterable(a 是一个列表)。

_list = [1,2]
_list.extend('abc')
_list
[1, 2, 'a', 'b', 'c']
_list.extend(range(2))
_list
[1, 2, 'a', 'b', 'c', 0, 1]

该方法是一个过程 (过程就是不返回有意义结果的函数;在 Python 中,过程的返回值为 None), 直接对原列表进行修改:

_list = [1,2]
a = _list.extend('abc')
print(a)
None

list.insert 插入一个元素

列表方法 list.insert(),Python 官方文档描述如下:

help(list.insert)
Help on method_descriptor:

insert(self, index, object, /)
    Insert object before index.

在给定的位置插入一个元素。第一个参数是要插入的元素的索引,所以 a.insert(0, x) 插入列表头部,a.insert(len(a), x) 等同于 a.append(x)(a 是一个列表)。

_list = [1,2,3]
_list.insert(0,0)
_list
[0, 1, 2, 3]
_list.insert(len(_list),[4])
_list
[0, 1, 2, 3, [4]]

该方法是一个过程 (过程就是不返回有意义结果的函数;在 Python 中,过程的返回值为 None), 直接对原列表进行修改:

_list = [1,2,3]
a = _list.insert(0,0)
print(a)
None

list.sort 对列表原地排序

列表方法 list.sort(),Python 官方文档描述如下:

help(list.sort)
Help on method_descriptor:

sort(self, /, *, key=None, reverse=False)
    Sort the list in ascending order and return None.
    
    The sort is in-place (i.e. the list itself is modified) and stable (i.e. the
    order of two equal elements is maintained).
    
    If a key function is given, apply it once to each list item and sort them,
    ascending or descending, according to their function values.
    
    The reverse flag can be set to sort in descending order.

此方法会对列表进行原地排序,只使用 < 来进行各项间比较。异常不会被屏蔽——如果有任何比较操作失败,整个排序操作将失败(而列表可能会处于被部分修改的状态)。

_list = [2,3,6,1,'5']
_list.sort()
---------------------------------------------------------------------------

TypeError                                 Traceback (most recent call last)

<ipython-input-2-87abda0b5baf> in <module>
      1 _list = [2,3,6,1,'5']
----> 2 _list.sort()


TypeError: '<' not supported between instances of 'str' and 'int'
_list
[1, 2, 3, 6, '5']

sort() 接受两个仅限以关键字形式传入的参数 (仅限关键字参数):

  • key 指定带有一个参数的函数,应用于列表中的每一个元素,按求值之后的大小,对原列表进行排序。默认值 None 表示直接对列表项排序。
_list = [-3,2,-5,1,4]
_list.sort(key=abs)
_list
[1, 2, -3, 4, -5]
_list.sort()
_list
[-5, -3, 1, 2, 4]
  • reverse 为一个布尔值。如果设为 True,则每个列表元素将按反向顺序比较进行排序。
_list = [-3,2,-5,1,4]
_list.sort(reverse=True)
_list
[4, 2, 1, -3, -5]

当对较大的列表排序时,此方法会原地修改该序列以保证空间经济性。因此它并不会返回排序后的序列。

sort() 方法确保是稳定的——如果一个排序确保不会改变比较结果相等的元素的相对顺序就称其为稳定的。

_list = [1,'1.0',2,'1']
_list.sort(key=float)
_list
[1, '1.0', '1', 2]

该方法是一个过程 (过程就是不返回有意义结果的函数;在 Python 中,过程的返回值为 None), 直接对原列表进行修改:

_list = [5,1,4]
a = _list.sort()
print(a)
None

list.reverse 反转列表中元素

列表方法 list.reverse(),Python 官方文档描述如下:

help(list.reverse)
Help on method_descriptor:

reverse(self, /)
    Reverse *IN PLACE*.

反转列表中的元素。

_list = [1,2,3]
_list.reverse()
_list
[3, 2, 1]

该方法是一个过程 (过程就是不返回有意义结果的函数;在 Python 中,过程的返回值为 None), 直接对原列表进行修改:

_list = [1,2,3]
a = _list.reverse()
print(a)
None

list.pop 删除元素并返回

列表方法 list.pop(),Python 官方文档描述如下:

help(list.pop)
Help on method_descriptor:

pop(self, index=-1, /)
    Remove and return item at index (default last).
    
    Raises IndexError if list is empty or index is out of range.

删除列表中给定位置的元素并返回它。如果没有给定位置,list.pop() 将会删除并返回列表中的最后一个元素。给定位置超出范围,抛出 IndexError 错误。

_list = [1,2,3,4]
_list.pop()
4
_list
[1, 2, 3]
_list.pop(0)
1
_list
[2, 3]
_list.pop(5)
---------------------------------------------------------------------------

IndexError                                Traceback (most recent call last)

<ipython-input-4-efa5a84417c8> in <module>
----> 1 _list.pop(5)


IndexError: pop index out of range

list.remove 移除一个元素

列表方法 list.remove(),Python 官方文档描述如下:

help(list.remove)
Help on method_descriptor:

remove(self, value, /)
    Remove first occurrence of value.
    
    Raises ValueError if the value is not present.

移除列表中第一个值为 value 的元素。如果没有这样的元素,则抛出 ValueError 异常。

_list = [1,3,2,3]
_list.remove(3)
_list
[1, 2, 3]
_list.remove(4)
---------------------------------------------------------------------------

ValueError                                Traceback (most recent call last)

<ipython-input-3-5747ddae04fe> in <module>
----> 1 _list.remove(4)


ValueError: list.remove(x): x not in list

该方法是一个过程 (过程就是不返回有意义结果的函数;在 Python 中,过程的返回值为 None), 直接对原列表进行修改:

_list = [1,3,2,3]
a = _list.remove(3)
print(a)
None

list.count 统计元素出现次数

列表方法 list.count(),Python 官方文档描述如下:

help(list.count)
Help on method_descriptor:

count(self, value, /)
    Return number of occurrences of value.

返回元素 value 在列表中出现的次数,没有出现为 0。

_list = [1,2,3,1]
_list.count(1), _list.count([1])
(2, 0)

list.index 查找最小索引

列表方法 list.index(),Python 官方文档描述如下:

help(list.index)
Help on method_descriptor:

index(self, value, start=0, stop=9223372036854775807, /)
    Return first index of value.
    
    Raises ValueError if the value is not present.

返回列表中第一个值为 value 的元素从零开始的索引。如果没有这样的元素将会抛出 ValueError 异常。

可选参数 start 和 stop 是切片符号,用于将搜索限制为列表的特定子序列。返回的是相对于整个序列开始计算的索引,而不是相对于 start 参数。

_list = [1,2,3,4,3]
_list.index(3)
2
_list.index(3,1,4)
2
_list.index(3,4,10)
4
_list.index(3,5,10)
---------------------------------------------------------------------------

ValueError                                Traceback (most recent call last)

<ipython-input-6-3e258cbffc85> in <module>
----> 1 _list.index(3,5,10)


ValueError: 3 is not in list

list.copy 列表的一个浅拷贝

列表方法 list.copy(),Python 官方文档描述如下:

help(list.copy)
Help on method_descriptor:

copy(self, /)
    Return a shallow copy of the list.

返回列表的一个浅拷贝。相当于 a[:](a 是一个列表)。浅拷贝得到新的列表,列表中有可变对象时,浅拷贝中的可变对象元素,是原列表中同一个对象的多次引用。

list_1 = [[1],2,3]
list_2 = list_1.copy()
print(list_2)
id(list_1),id(list_2)
[[1], 2, 3]


(2622792783240, 2622792782728)
# 同一个对象
id(list_1[0]), id(list_2[0])
(2622792782792, 2622792782792)

改变其中一个都会跟着改变:

list_1[0][:] = 'abc'
list_1, list_2
([['a', 'b', 'c'], 2, 3], [['a', 'b', 'c'], 2, 3])