Python实战第6期:列表与元组

引言:为什么需要列表和元组?

在前面的课程中,我们使用变量来存储单个数据。但如果需要存储一组数据呢?

比如:

  • 存储一个班级所有学生的名字
  • 存储一个月的每天温度
  • 存储购物车里的所有商品

如果为每个数据创建一个变量,会非常麻烦。这时候就需要用到列表 和元组。

列表和元组都是用来存储一组数据的容器,它们的区别在于:列表可以修改,元组不能修改。


一、列表的创建和操作

1. 创建列表

列表 是Python中最常用的数据结构,用方括号 [] 表示,元素之间用逗号分隔。

python 复制代码
# 创建空列表
empty_list = []
print(empty_list)  # 输出:[]

# 创建包含数字的列表
numbers = [1, 2, 3, 4, 5]
print(numbers)  # 输出:[1, 2, 3, 4, 5]

# 创建包含字符串的列表
fruits = ["苹果", "香蕉", "橙子"]
print(fruits)  # 输出:['苹果', '香蕉', '橙子']

# 创建包含不同类型数据的列表
mixed = [1, "hello", 3.14, True]
print(mixed)  # 输出:[1, 'hello', 3.14, True]

# 使用list()函数创建列表
numbers = list(range(1, 6))
print(numbers)  # 输出:[1, 2, 3, 4, 5]

💡 提示:列表中的元素可以是任意类型,甚至可以嵌套列表。

2. 访问列表元素

列表中的每个元素都有一个索引(从0开始),可以通过索引访问元素。

python 复制代码
fruits = ["苹果", "香蕉", "橙子", "葡萄"]

# 正向索引(从0开始)
print(fruits[0])  # 输出:苹果
print(fruits[1])  # 输出:香蕉
print(fruits[2])  # 输出:橙子
print(fruits[3])  # 输出:葡萄

# 反向索引(从-1开始)
print(fruits[-1])  # 输出:葡萄
print(fruits[-2])  # 输出:橙子
print(fruits[-3])  # 输出:香蕉
print(fruits[-4])  # 输出:苹果

⚠️ 警告 :索引超出范围会报错 IndexError

python 复制代码
fruits = ["苹果", "香蕉", "橙子"]
# print(fruits[5])  # IndexError: list index out of range

3. 修改列表元素

列表是可变的,可以通过索引修改元素。

python 复制代码
numbers = [1, 2, 3, 4, 5]
print(numbers)  # 输出:[1, 2, 3, 4, 5]

# 修改第3个元素(索引为2)
numbers[2] = 30
print(numbers)  # 输出:[1, 2, 30, 4, 5]

# 修改多个元素
numbers[0:2] = [10, 20]
print(numbers)  # 输出:[10, 20, 30, 4, 5]

4. 列表切片

切片用于获取列表的一部分,语法是 list[start:end:step]。

python 复制代码
numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

# 基本切片 [start:end](不包含end)
print(numbers[0:5])   # 输出:[0, 1, 2, 3, 4]
print(numbers[2:7])   # 输出:[2, 3, 4, 5, 6]

# 省略start,从开头开始
print(numbers[:5])    # 输出:[0, 1, 2, 3, 4]

# 省略end,到结尾结束
print(numbers[5:])    # 输出:[5, 6, 7, 8, 9]

# 省略start和end,复制整个列表
print(numbers[:])     # 输出:[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

# 使用步长
print(numbers[::2])   # 输出:[0, 2, 4, 6, 8]
print(numbers[1::2])  # 输出:[1, 3, 5, 7, 9]

# 反转列表
print(numbers[::-1])  # 输出:[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]

5. 列表运算

python 复制代码
# 列表拼接
list1 = [1, 2, 3]
list2 = [4, 5, 6]
result = list1 + list2
print(result)  # 输出:[1, 2, 3, 4, 5, 6]

# 列表重复
list1 = [1, 2, 3]
result = list1 * 3
print(result)  # 输出:[1, 2, 3, 1, 2, 3, 1, 2, 3]

# 判断元素是否在列表中
fruits = ["苹果", "香蕉", "橙子"]
print("苹果" in fruits)      # 输出:True
print("葡萄" in fruits)      # 输出:False
print("葡萄" not in fruits)  # 输出:True

6. 列表长度

python 复制代码
fruits = ["苹果", "香蕉", "橙子", "葡萄"]
print(len(fruits))  # 输出:4

# 获取最后一个元素
print(fruits[len(fruits) - 1])  # 输出:葡萄
# 更简单的方式
print(fruits[-1])  # 输出:葡萄

二、列表常用方法

1. 添加元素

python 复制代码
fruits = ["苹果", "香蕉"]

# append() - 在末尾添加一个元素
fruits.append("橙子")
print(fruits)  # 输出:['苹果', '香蕉', '橙子']

# insert() - 在指定位置插入元素
fruits.insert(1, "葡萄")
print(fruits)  # 输出:['苹果', '葡萄', '香蕉', '橙子']

# extend() - 在末尾添加多个元素
fruits.extend(["西瓜", "芒果"])
print(fruits)  # 输出:['苹果', '葡萄', '香蕉', '橙子', '西瓜', '芒果']

# 使用 + 运算符
fruits = fruits + ["草莓"]
print(fruits)  # 输出:['苹果', '葡萄', '香蕉', '橙子', '西瓜', '芒果', '草莓']

2. 删除元素

python 复制代码
fruits = ["苹果", "香蕉", "橙子", "葡萄", "西瓜"]

# remove() - 删除第一个匹配的元素
fruits.remove("香蕉")
print(fruits)  # 输出:['苹果', '橙子', '葡萄', '西瓜']

# pop() - 删除指定位置的元素,并返回该元素
removed = fruits.pop(1)
print(removed)  # 输出:橙子
print(fruits)   # 输出:['苹果', '葡萄', '西瓜']

# pop() - 不指定位置,默认删除最后一个
removed = fruits.pop()
print(removed)  # 输出:西瓜
print(fruits)   # 输出:['苹果', '葡萄']

# del - 删除指定位置的元素
del fruits[0]
print(fruits)  # 输出:['葡萄']

# clear() - 清空列表
fruits.clear()
print(fruits)  # 输出:[]

💡 提示:

  • remove() 删除第一个匹配的元素,如果元素不存在会报错
  • pop() 返回被删除的元素,remove() 不返回

3. 查找元素

python 复制代码
fruits = ["苹果", "香蕉", "橙子", "香蕉", "葡萄"]

# index() - 查找元素的索引(第一个匹配)
print(fruits.index("香蕉"))  # 输出:1

# 指定查找范围
print(fruits.index("香蕉", 2))  # 输出:3(从索引2开始查找)

# count() - 统计元素出现的次数
print(fruits.count("香蕉"))  # 输出:2
print(fruits.count("苹果"))  # 输出:1
print(fruits.count("西瓜"))  # 输出:0

# in - 判断元素是否存在
print("香蕉" in fruits)  # 输出:True
print("西瓜" in fruits)  # 输出:False

4. 排序

python 复制代码
numbers = [3, 1, 4, 1, 5, 9, 2, 6, 5]

# sort() - 原地排序(修改原列表)
numbers.sort()
print(numbers)  # 输出:[1, 1, 2, 3, 4, 5, 5, 6, 9]

# 降序排序
numbers.sort(reverse=True)
print(numbers)  # 输出:[9, 6, 5, 5, 4, 3, 2, 1, 1]

# sorted() - 返回新列表,不修改原列表
numbers = [3, 1, 4, 1, 5, 9, 2, 6, 5]
new_list = sorted(numbers)
print(numbers)   # 输出:[3, 1, 4, 1, 5, 9, 2, 6, 5](原列表不变)
print(new_list)  # 输出:[1, 1, 2, 3, 4, 5, 5, 6, 9]

# 反转列表
numbers.reverse()
print(numbers)  # 输出:[5, 6, 2, 9, 5, 1, 4, 1, 3]

# 使用 [::-1] 反转(不修改原列表)
numbers = [1, 2, 3, 4, 5]
reversed_list = numbers[::-1]
print(numbers)        # 输出:[1, 2, 3, 4, 5]
print(reversed_list)  # 输出:[5, 4, 3, 2, 1]

5. 复制列表

python 复制代码
# 使用 copy() 方法
fruits = ["苹果", "香蕉", "橙子"]
fruits_copy = fruits.copy()
print(fruits_copy)  # 输出:['苹果', '香蕉', '橙子']

# 使用切片
fruits_copy = fruits[:]
print(fruits_copy)  # 输出:['苹果', '香蕉', '橙子']

# 使用 list() 函数
fruits_copy = list(fruits)
print(fruits_copy)  # 输出:['苹果', '香蕉', '橙子']

# ⚠️ 注意:直接赋值不是复制
fruits = ["苹果", "香蕉", "橙子"]
fruits_ref = fruits  # 这只是引用,不是复制
fruits_ref.append("葡萄")
print(fruits)  # 输出:['苹果', '香蕉', '橙子', '葡萄'](原列表也被修改了)

6. 列表推导式

列表推导式是创建列表的简洁方式。

python 复制代码
# 基本语法:[表达式 for 变量 in 序列]

# 创建1到10的平方列表
squares = [x**2 for x in range(1, 11)]
print(squares)  # 输出:[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

# 筛选偶数
evens = [x for x in range(1, 21) if x % 2 == 0]
print(evens)  # 输出:[2, 4, 6, 8, 10, 12, 14, 16, 18, 20]

# 字符串处理
words = ["hello", "world", "python"]
upper_words = [word.upper() for word in words]
print(upper_words)  # 输出:['HELLO', 'WORLD', 'PYTHON']

# 嵌套列表
matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
flat = [num for row in matrix for num in row]
print(flat)  # 输出:[1, 2, 3, 4, 5, 6, 7, 8, 9]

💡 提示:列表推导式比等价的for循环更简洁,执行速度也更快。


三、元组的特点

1. 什么是元组

元组 与列表类似,但元组是不可变的,用圆括号 () 表示。

python 复制代码
# 创建元组
empty_tuple = ()
print(empty_tuple)  # 输出:()

# 创建包含元素的元组
numbers = (1, 2, 3, 4, 5)
print(numbers)  # 输出:(1, 2, 3, 4, 5)

# 创建包含不同类型数据的元组
mixed = (1, "hello", 3.14, True)
print(mixed)  # 输出:(1, 'hello', 3.14, True)

# 创建单个元素的元组(注意逗号)
single = (5,)  # 必须有逗号
print(single)  # 输出:(5,)
print(type(single))  # 输出:<class 'tuple'>

# 没有逗号的情况
not_tuple = (5)
print(not_tuple)  # 输出:5
print(type(not_tuple))  # 输出:<class 'int'>

💡 提示:创建单个元素的元组时,必须加逗号,否则Python会把它当作普通数据类型。

2. 元组的不可变性

元组创建后不能修改,这是元组和列表的最大区别。

python 复制代码
# 列表可以修改
fruits = ["苹果", "香蕉", "橙子"]
fruits[0] = "葡萄"
print(fruits)  # 输出:['葡萄', '香蕉', '橙子']

# 元组不能修改
numbers = (1, 2, 3, 4, 5)
# numbers[0] = 10  # TypeError: 'tuple' object does not support item assignment

💡 提示:元组的不可变性使得它比列表更安全,可以作为字典的键。

3. 元组的操作

虽然元组不能修改,但可以进行一些操作。

python 复制代码
numbers = (1, 2, 3, 4, 5, 2, 3)

# 访问元素
print(numbers[0])   # 输出:1
print(numbers[-1])  # 输出:3

# 切片
print(numbers[1:4])  # 输出:(2, 3, 4)

# 长度
print(len(numbers))  # 输出:7

# 计数
print(numbers.count(2))  # 输出:2

# 查找索引
print(numbers.index(3))  # 输出:2

# 判断元素是否存在
print(3 in numbers)  # 输出:True
print(10 in numbers)  # 输出:False

4. 元组的解包

元组解包是Python的一个强大特性。

python 复制代码
# 基本解包
point = (3, 4)
x, y = point
print(x)  # 输出:3
print(y)  # 输出:4

# 交换变量
a = 1
b = 2
a, b = b, a
print(a)  # 输出:2
print(b)  # 输出:1

# 使用 * 收集剩余元素
numbers = (1, 2, 3, 4, 5)
first, *rest = numbers
print(first)  # 输出:1
print(rest)   # 输出:[2, 3, 4, 5]

first, second, *rest = numbers
print(first)   # 输出:1
print(second)  # 输出:2
print(rest)    # 输出:[3, 4, 5]

# 在函数返回值中使用
def get_min_max(numbers):
    return min(numbers), max(numbers)

minimum, maximum = get_min_max([3, 1, 4, 1, 5, 9, 2, 6])
print(f"最小值:{minimum},最大值:{maximum}")

5. 元组与列表的转换

python 复制代码
# 列表转元组
fruits_list = ["苹果", "香蕉", "橙子"]
fruits_tuple = tuple(fruits_list)
print(fruits_tuple)  # 输出:('苹果', '香蕉', '橙子')

# 元组转列表
numbers_tuple = (1, 2, 3, 4, 5)
numbers_list = list(numbers_tuple)
print(numbers_list)  # 输出:[1, 2, 3, 4, 5]

# 修改"元组"的技巧:转换为列表,修改后再转回元组
numbers = (1, 2, 3, 4, 5)
numbers_list = list(numbers)
numbers_list[0] = 10
numbers = tuple(numbers_list)
print(numbers)  # 输出:(10, 2, 3, 4, 5)

6. 元组的使用场景

python 复制代码
# 1. 函数返回多个值
def get_user_info():
    name = "小明"
    age = 25
    city = "北京"
    return name, age, city  # 返回元组

name, age, city = get_user_info()
print(f"姓名:{name},年龄:{age},城市:{city}")

# 2. 作为字典的键(列表不能作为字典的键)
locations = {
    (39.9, 116.4): "北京",
    (31.2, 121.5): "上海",
    (23.1, 113.3): "广州"
}
print(locations[(39.9, 116.4)])  # 输出:北京

# 3. 数据不可变的场景
RGB_RED = (255, 0, 0)
RGB_GREEN = (0, 255, 0)
RGB_BLUE = (0, 0, 255)

# 4. 命名元组(更高级的用法)
from collections import namedtuple

Point = namedtuple('Point', ['x', 'y'])
p = Point(3, 4)
print(p.x)  # 输出:3
print(p.y)  # 输出:4

四、列表与元组的对比

特性 列表 元组
符号 [] ()
可变性 可变 不可变
性能 较慢 较快
内存占用 较大 较小
可作为字典键 不可以 可以
适用场景 数据需要修改 数据不需要修改
python 复制代码
# 性能对比
import sys

# 列表
list_example = [1, 2, 3, 4, 5]
print(f"列表大小:{sys.getsizeof(list_example)} bytes")

# 元组
tuple_example = (1, 2, 3, 4, 5)
print(f"元组大小:{sys.getsizeof(tuple_example)} bytes")

💡 提示:如果数据不需要修改,优先使用元组,因为它更节省内存,执行速度也更快。


五、实战练习

练习1:学生成绩管理

python 复制代码
# 存储学生成绩
students = [
    ("张三", 85),
    ("李四", 92),
    ("王五", 78),
    ("赵六", 95),
    ("钱七", 88)
]

# 计算平均分
total = sum(score for name, score in students)
average = total / len(students)
print(f"平均分:{average:.1f}")

# 找出最高分和最低分
highest = max(students, key=lambda x: x[1])
lowest = min(students, key=lambda x: x[1])
print(f"最高分:{highest[0]}({highest[1]}分)")
print(f"最低分:{lowest[0]}({lowest[1]}分)")

# 按成绩排序
sorted_students = sorted(students, key=lambda x: x[1], reverse=True)
print("\n成绩排名:")
for i, (name, score) in enumerate(sorted_students, 1):
    print(f"{i}. {name}:{score}分")

练习2:购物车管理

python 复制代码
# 购物车
cart = []

# 添加商品
def add_item(name, price, quantity=1):
    cart.append((name, price, quantity))
    print(f"已添加:{name},单价:{price},数量:{quantity}")

# 删除商品
def remove_item(name):
    for i, item in enumerate(cart):
        if item[0] == name:
            cart.pop(i)
            print(f"已删除:{name}")
            return
    print(f"未找到:{name}")

# 计算总价
def total_price():
    total = sum(price * quantity for name, price, quantity in cart)
    return total

# 显示购物车
def show_cart():
    if not cart:
        print("购物车为空")
        return
    
    print("\n购物车内容:")
    print("-" * 40)
    for name, price, quantity in cart:
        print(f"{name}:{price}元 × {quantity} = {price * quantity}元")
    print("-" * 40)
    print(f"总计:{total_price()}元")

# 测试
add_item("苹果", 5.5, 3)
add_item("香蕉", 3.0, 2)
add_item("橙子", 4.5, 1)
show_cart()

remove_item("香蕉")
show_cart()

练习3:矩阵转置

python 复制代码
# 原始矩阵
matrix = [
    [1, 2, 3],
    [4, 5, 6],
    [7, 8, 9]
]

# 方法1:使用列表推导式
transposed = [[matrix[j][i] for j in range(len(matrix))] for i in range(len(matrix[0]))]

print("原始矩阵:")
for row in matrix:
    print(row)

print("\n转置后:")
for row in transposed:
    print(row)

# 方法2:使用zip()
transposed = list(zip(*matrix))
print("\n使用zip()转置:")
for row in transposed:
    print(row)

练习4:统计词频

python 复制代码
# 文本
text = """
Python是一种广泛使用的高级编程语言。
Python的设计哲学强调代码的可读性和简洁的语法。
Python支持多种编程范式,包括面向对象、命令式、函数式和过程式编程。
"""

# 统计词频
words = text.replace("。", "").replace(",", "").replace("、", "").split()
word_count = {}

for word in words:
    if word in word_count:
        word_count[word] += 1
    else:
        word_count[word] = 1

# 按频率排序
sorted_words = sorted(word_count.items(), key=lambda x: x[1], reverse=True)

print("词频统计:")
for word, count in sorted_words[:10]:
    print(f"{word}:{count}次")

六、常见问题与排错

问题1:索引超出范围

原因 :访问了不存在的索引 解决方法:确保索引在有效范围内

python 复制代码
fruits = ["苹果", "香蕉", "橙子"]
# print(fruits[5])  # IndexError: list index out of range

# 正确做法:先检查长度
if len(fruits) > 5:
    print(fruits[5])
else:
    print("索引超出范围")

问题2:修改元组报错

原因 :元组是不可变的 解决方法:如果需要修改,使用列表

python 复制代码
numbers = (1, 2, 3)
# numbers[0] = 10  # TypeError

# 如果需要修改,转换为列表
numbers_list = list(numbers)
numbers_list[0] = 10
numbers = tuple(numbers_list)

问题3:列表引用问题

原因 :直接赋值只是创建引用,不是复制 解决方法:使用 copy() 或切片

python 复制代码
# ❌ 错误
list1 = [1, 2, 3]
list2 = list1  # 只是引用
list2.append(4)
print(list1)  # 输出:[1, 2, 3, 4](list1也被修改了)

# ✅ 正确
list1 = [1, 2, 3]
list2 = list1.copy()  # 或 list1[:]
list2.append(4)
print(list1)  # 输出:[1, 2, 3](list1不变)
print(list2)  # 输出:[1, 2, 3, 4]

七、本篇小结

今天,我们完成了以下学习内容:

  1. 列表的创建和操作:

    • 使用 [] 创建列表
    • 通过索引访问和修改元素
    • 列表切片
    • 列表运算(拼接、重复、判断)
  2. 列表常用方法:

    • 添加:append()、insert()、extend()
    • 删除:remove()、pop()、del、clear()
    • 查找:index()、count()、in
    • 排序:sort()、sorted()、reverse()
    • 复制:copy()、切片、list()
  3. 元组的特点:

    • 使用 () 创建元组
    • 元组是不可变的
    • 元组解包
    • 元组与列表的转换
    • 元组的使用场景

请记住这三个结论:

  1. 列表是可变的:适合存储需要修改的数据
  2. 元组是不可变的:适合存储不需要修改的数据,更安全、更高效
  3. 列表推导式很强大:用简洁的方式创建和处理列表

下期预告

在第7期中,我们将学习Python的字典和集合,包括:

  • 字典的创建和基本操作
  • 字典的常用方法
  • 集合的概念和操作
  • 字典和集合的应用场景

敬请期待!


✍坚持原创,求关注,点赞,收藏

相关推荐
用户817595220131 小时前
QNAP NAS 部署 Vaultwarden:使用 Cloudflare Tunnel 实现外网访问与手机同步
后端
日耗10亿Token被老板赶出门1 小时前
大模型接口返回 200,为什么程序还是报错?
python
嘿嘿嘿9151 小时前
Java 第四周学习笔记:多态、接口、内部类与 String
后端
彩雲演文1 小时前
51单片机万年历Proteus仿真跑通实录:LCD12864B+DS1302+DHT11,带农历和闹钟(效果图+接线表+全套源码)
后端
小小张说故事1 小时前
Python 的 __new__ 到底管什么?和 __init__ 的分工一次讲透Python后端python知识整理日新计划
python
ThinkerQAQ_1 小时前
并发编程(十):BlockingQueue 与 Channel 的实现——从 Runtime 到 CPU
后端
霂鳯1 小时前
新手勇闯网络安全 | PHP基础(四)
后端
海岳云舟1 小时前
程序常驻后台运行的原理和方法
后端·全栈
彩雲演文1 小时前
Proteus仿真LCD12864B不显示/黄屏?别急着改接线,真凶是BusyCheck死循环(51单片机实战排查)
后端