在 C++ 和 Java 中,容器是需要你显式命名并构造的 library class。 Python 则把容器直接放进了语法:[1, 2]、{"a": 1} 和 {1, 2} 都是字面量,in 和 len() 可以作用于它们全部, 切片可以作用于各种序列,而且这些都不需要导入任何东西。 列表、元组、字典和集合都是基础数据类型。
for 语句会直接遍历列表,而不是先遍历一串数字索引:
# list.py
odds = [1, 3, 5, 7, 9, 11]
print(odds)
#: [1, 3, 5, 7, 9, 11]
odds.append(13)
for x in odds:
print(x)
#: 1
#: 3
#: 5
#: 7
#: 9
#: 11
#: 13
第一行创建一个 list。 append() 向 odds 添加新元素。 list 会自动调整自身大小。 for 语句遍历 odds, 因此 x 会依次取得 list 中的每个值。
list 可以容纳任意种类的对象,是一个有序、可变的序列。 索引从零开始,负索引从末尾倒数。 切片(slice) [start:stop:step] 会复制一个子区间,其中不包含 stop:
# slicing.py
xs = [10, 20, 30, 40, 50]
print(xs[0], xs[-1]) # First and last
#: 10 50
print(xs[1:3]) # The stop index is excluded
#: [20, 30]
print(xs[:2]) # From the start
#: [10, 20]
print(xs[2:]) # To the end
#: [30, 40, 50]
print(xs[::2]) # Every second item
#: [10, 30, 50]
print(xs[::-1]) # Reversed
#: [50, 40, 30, 20, 10]
切片适用于任何序列,包括字符串和元组。
列表可以增长、收缩,也能回答关于自身的问题:
# list_ops.py
xs = [10, 20, 30]
xs.append(40) # Add one item at the end
xs.extend([50, 60]) # Add every item of an iterable
xs.insert(1, 15) # Insert before index 1
print(xs, len(xs))
#: [10, 15, 20, 30, 40, 50, 60] 7
xs.remove(15) # Remove the first item equal to 15
del xs[0] # Remove by index
print(xs, 30 in xs)
#: [20, 30, 40, 50, 60] True
append() 会把它的参数作为单个元素加入, 因此 xs.append([1, 2]) 会把一个 list 放进另一个 list。 extend() 则会逐个加入参数中的每一项。
sorted() 可以从任意 iterable 构造一个新的已排序列表。 list.sort() 会原地重新排列列表,并返回 None:
# sorting.py
words = ["pear", "Fig", "apple"]
print(sorted(words)) # A new list; words is untouched
#: ['Fig', 'apple', 'pear']
print(words)
#: ['pear', 'Fig', 'apple']
print(words.sort()) # Sorts in place and returns None
#: None
print(words)
#: ['Fig', 'apple', 'pear']
print(sorted(words, reverse=True))
#: ['pear', 'apple', 'Fig']
sorted(x) 返回排序后的结果,而 x.sort() 返回 None, 因此 x = x.sort() 会把 x 绑定到 None,从而丢掉原来的列表。 大写字母排在小写字母之前,因为 Python 按 code point 比较字符串。 函数会说明如何使用 key= 改变这一行为。
list 并不要求所有元素属于同一种类型。 由于每个槽位保存的只是你放进去的某个对象的引用, 同一个 list 可以同时混合字符串、数字、None 和其他容器:
# mixed_types.py
mixed = [1, "two", 3.0, True, None, [5, 6]]
for item in mixed:
print(item, type(item).__name__)
#: 1 int
#: two str
#: 3.0 float
#: True bool
#: None NoneType
#: [5, 6] list
混合类型很方便,但也很容易被滥用。 一个混合多种类型的 list,通常意味着每个元素都需要不同的处理逻辑。 这种情况通常用 tuple、data class, 或者若干个各自只保存一种类型的独立列表,表达得更好。
有两个列表操作很容易带来意外。 * 重复的是引用,而不是复制引用所指向的对象, 因此用这种方式构造出来的网格,实际上是三个名称共同指向同一行: