使用list和tuple

Python 作为入门友好的编程语言,容器类型(可装多个数据的结构)是绕不开的第一课。而 list(列表)tuple(元组)就是使用率最高的「有序序列双容器」——它们都能存任意类型的元素、都支持索引切片,但一个「想改就改」,一个「一旦创建就不许动(结构不许动,内容看元素)」。今天就把这俩的用法、区别、最佳实践全讲明白~


列表(List)

列表是Python中最基础的可变有序序列,适合存储需要动态增删改的数据。

创建列表

列表用方括号 [] 包裹元素,元素之间用逗号分隔:

# 1. 创建同类型的字符串列表
classmates = ['Michael', 'Bob', 'Tracy']
print(classmates)  # 输出: ['Michael', 'Bob', 'Tracy']

# 2. 创建混合类型的列表(Python灵活但不推荐,尽量保持同类型提升效率)
mixed_list = ['Apple', 123, True, 3.14]
print(mixed_list)

# 3. 创建空列表
empty_list = []
print(empty_list)  # 输出: []

访问列表元素

索引(下标)定位元素,有两个核心规则:

⚠️ 注意!新手常踩坑

  1. 索引永远从0开始(不是1);
  2. 负数索引从-1(最后一个元素)倒推,比如-2是倒数第二个;
  3. 索引越界会直接抛出 IndexError: list index out of range
print(classmates[0])   # 输出: 'Michael' (第一个元素)
print(classmates[-1])  # 输出: 'Tracy' (最后一个元素)

# 索引越界会报错
# print(classmates[3])  # IndexError

列表常用操作

1. 获取列表长度

用Python内置的通用长度函数 len()

print(len(classmates))  # 输出: 3

2. 修改元素

直接通过索引赋值即可:

classmates[1] = 'Sarah'
print(classmates)  # 输出: ['Michael', 'Sarah', 'Tracy']

3. 添加元素

有三种常用方法,各有适用场景:

# 方法1:append() —— 末尾追加单个元素,效率O(1)!大列表优先用
classmates.append('Adam')
print(classmates)  # 输出: ['Michael', 'Sarah', 'Tracy', 'Adam']

# 方法2:insert(i, x) —— 指定位置i插入元素x,效率O(n)(后面元素要后移)
classmates.insert(1, 'Jack')
print(classmates)  # 输出: ['Michael', 'Jack', 'Sarah', 'Tracy', 'Adam']

# 方法3:extend(iterable) —— 一次性追加多个元素,循环append的替代方案
classmates.extend(['Lily', 'Lucy'])
print(classmates)  # 输出调整后的完整列表

4. 删除元素

三种常用方法:

# 方法1:pop() —— 不传索引删末尾(和append配对,效率O(1)),传索引删指定位置,返回被删元素
last = classmates.pop()
print(last)        # 输出: 'Lucy'
print(classmates)  # 输出少了Lucy的列表

second = classmates.pop(1)
print(second)      # 输出: 'Jack'

# 方法2:remove(x) —— 删除**第一个匹配的值**x,值不存在会抛ValueError
classmates.remove('Sarah')
print(classmates)  # 输出调整后的列表

# 方法3:del 语句 —— 直接删除指定位置/切片,无返回值
del classmates[1]  # 删除索引1的元素
print(classmates)

多维列表(嵌套列表)

列表可以套列表,形成二维/三维数据结构(比如模拟矩阵、网格):

# 模拟3x3的二维矩阵
matrix = [
    [1, 2, 3],
    [4, 5, 6],
    [7, 8, 9]
]
print(matrix[1][1])  # 输出: 5(第二行第二列,索引从0开始)

# 混合嵌套(不推荐同层混合类型)
nested_list = ['python', 'java', ['asp', 'php'], 'scheme']
print(nested_list[2][1])  # 输出: 'php'

💡 实用小技巧:想快速拿到二维列表的某一列?可以用 zip(*matrix) 先转置(结果是元组的迭代器,转成列表要加 list()),后面学迭代器时会更深入~


列表切片(超级好用的功能!)

切片可以一次性访问列表的子集,完整语法是 list[start:end:step],三个参数都可选

  • start:起始索引(默认0,包含)
  • end:结束索引(默认到末尾,不包含)
  • step:步长(默认1,负数表示反向)
numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

# 1. 基本切片
print(numbers[2:5])   # 输出: [2, 3, 4]
print(numbers[:3])    # 输出: [0, 1, 2](从头开始)
print(numbers[5:])    # 输出: [5, 6, 7, 8, 9](到末尾结束)
print(numbers[:])     # 输出完整列表(相当于浅拷贝)

# 2. 步长切片
print(numbers[::2])   # 输出: [0, 2, 4, 6, 8](隔一个取一个)
print(numbers[1::2])  # 输出: [1, 3, 5, 7, 9]

# 3. 反向切片(一行代码反转列表!Pythonic写法)
print(numbers[::-1])  # 输出: [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]

元组(Tuple)

元组是Python中伪不可变的有序序列,适合存储不应修改的固定数据

创建元组

元组用圆括号 () 包裹元素(有时可省略,比如函数返回、元组解包),但有一个超级重要的规则

⚠️ 超级警告! 创建仅含一个元素的元组,必须加逗号!否则Python会把它当成普通的括号运算符(优先级控制),创建的是单个值的变量!

# 1. 创建多元素元组
classmates = ('Michael', 'Bob', 'Tracy')
print(classmates)  # 输出: ('Michael', 'Bob', 'Tracy')

# 2. 创建单个元素的元组(必须加逗号!)
single_tuple = (1,)
print(single_tuple)       # 输出: (1,)
print(type(single_tuple)) # <class 'tuple'>

# 3. 不加逗号的错误示范
not_a_tuple = (1)
print(not_a_tuple)       # 输出: 1(整数)
print(type(not_a_tuple)) # <class 'int'>

# 4. 创建空元组
empty_tuple = ()
print(empty_tuple)  # 输出: ()

访问元组元素

和列表完全一致——索引、切片都能用!但因为不可变,不能修改、增删元素:

print(classmates[0])   # 输出: 'Michael'
print(classmates[-1])  # 输出: 'Tracy'

# 尝试修改会报错
# classmates[0] = 'Adam'  # TypeError: 'tuple' object does not support item assignment

元组的「伪不可变性」陷阱

元组的不可变性,指的是元组中每个元素的「引用地址」不可变!如果元素本身是可变对象(比如list、dict、set),我们可以修改这个可变对象的内容!这是新手常踩的小坑:

mixed_tuple = ('a', 'b', ['A', 'B'])
# ✅ 可以修改内部可变对象的内容
mixed_tuple[2][0] = 'X'
print(mixed_tuple)  # 输出: ('a', 'b', ['X', 'B'])

# ❌ 不能替换整个可变对象的引用
# mixed_tuple[2] = ['C', 'D']  # TypeError

元组解包(Tuple Unpacking)—— Pythonic的核心操作!

元组解包可以一次性把元组的元素赋值给多个变量,超级实用!

# 1. 基本坐标赋值
point = (3, 4)
x, y = point
print(x, y)  # 输出: 3 4

# 2. 函数返回多值(Python函数返回多值的本质就是返回元组!)
def get_size(file_path):
    # 假设这里读取了文件宽高
    return 1024, 2048  # 等价于 return (1024, 2048)
width, height = get_size("test.txt")
print(f"文件宽:{width}px,高:{height}px")

# 3. 快速交换变量(不用临时变量temp!)
a, b = 1, 2
a, b = b, a
print(f"交换后:a={a}, b={b}")

# 4. 遍历字典的键值对(items()返回的是键值对元组的迭代器)
user = {"name": "Alice", "age": 20}
for k, v in user.items():
    print(f"{k}: {v}")

List vs Tuple:核心对比速查表

特性列表(List)元组(Tuple)
语法符号方括号 []圆括号 ()(有时可省略)
可变性完全可变:支持增删改元素伪不可变:元素引用不可变,可变元素内容可改
性能表现稍慢:构建、遍历无缓存优化更快:Python对小不可变对象有缓存,内存占用更小
常用方法append()/insert()/extend() pop()/remove() sort()/reverse()极少:只有count(x)(统计出现次数)和index(x)(找第一个位置)
最佳适用场景1. 动态数据容器(待办列表、待排序数组)
2. 需要增删改的数据
1. 常量/固定配置(坐标、RGB颜色)
2. 函数返回多个值
3. 字典的键(必须是不可变对象)
4. 枚举值备选

小试牛刀(练手题)

L = [
    ['Apple', 'Google', 'Microsoft'],
    ['Java', 'Python', 'Ruby', 'PHP'],
    ['Adam', 'Bart', 'Bob']
]

# 1. 打印指定元素
print(L[0][0])  # Apple
print(L[1][1])  # Python
print(L[2][2])  # Bob

# 2. 判断变量类型(用type()验证更直观)
check_vars = [(), (1), [2], (3,), (4,5,6)]
for var in check_vars:
    print(f"{var} 的类型是:{type(var).__name__}")

预期输出:

Apple
Python
Bob
() 的类型是:tuple
1 的类型是:int
[2] 的类型是:list
(3,) 的类型是:tuple
(4, 5, 6) 的类型是:tuple

核心要点&场景速记

  1. 有序序列双容器:list和tuple都支持索引、切片、len()、迭代等通用操作;
  2. 核心区别看「变」
    • List:[],可变,灵活优先;
    • Tuple:()(单个元素加逗号!),伪不可变,性能/安全优先;
  3. 踩坑提醒:Tuple里的可变元素内容可以改,但引用不能换;
  4. 必学元组解包:这是Python代码简洁性的核心之一。

掌握list和tuple是Python编程的第一步,接下来的循环、函数、字典学习中,它们会无处不在~多写几遍练手题,很快就能上手啦!