欢迎来到 Python 的世界!今天,我们来认识两位新朋友:List (列表) 和 Tuple (元组)。它们都是用来存放数据的“容器”,但在性格上却有很大的不同。我们还将一起攻克两个非常基础但极其重要的概念:元组 (Tuple) 的创建,以及如何在嵌套的列表 (List) 中像 GPS 一样精确定位数据。
🛍️ List (列表):你灵活的数据购物篮
列表是 Python 中最常用的一种数据类型。你可以把它想象成一个有序的购物篮,可以随时往里面添加、删除或改变商品。
1. 创建和查看你的购物篮
# 创建一个装有同学名字的列表
classmates = ['Michael', 'Bob', 'Tracy']
# 打印出来看看
print(classmates)
# ==> ['Michael', 'Bob', 'Tracy']
# 查看购物篮里有多少件商品 (元素个数)
print(len(classmates))
# ==> 32. 精准取物:使用索引
每个商品在购物篮里都有一个固定的位置编号,这个编号就是索引 (index)。
📌 重要规则: 索引永远从 0 开始!
# 取出第 1 个同学 (索引为 0)
print(classmates[0])
# ==> 'Michael'
# 取出第 3 个同学 (索引为 2)
print(classmates[2])
# ==> 'Tracy'
# 尝试取出第 4 个同学 (索引为 3)
# print(classmates[3])
# ==> ⚠️ IndexError: list index out of range (错误:索引超出范围!)最后一个元素的索引永远是 len(classmates) - 1。
✨ 小技巧:倒着取物 用 -1 可以直接取出最后一个元素,-2 取出倒数第二个,以此类推。
# 取最后一个
print(classmates[-1])
# ==> 'Tracy'
# 取倒数第二个
print(classmates[-2])
# ==> 'Bob'3. 整理购物篮:增、删、改
列表的强大之处在于它的灵活性。
添加元素
append('新元素'): 在购物篮末尾添加。classmates.append('Adam') print(classmates) # ==> ['Michael', 'Bob', 'Tracy', 'Adam']insert(索引, '新元素'): 在指定位置插入。classmates.insert(1, 'Jack') print(classmates) # ==> ['Michael', 'Jack', 'Bob', 'Tracy', 'Adam']
删除元素
pop(): 删除并返回购物篮末尾的元素。last_student = classmates.pop() print(f"被删除的同学是: {last_student}") # ==> 被删除的同学是: Adam print(classmates) # ==> ['Michael', 'Jack', 'Bob', 'Tracy']pop(索引): 删除并返回指定位置的元素。classmates.pop(1) # 删除索引为 1 的 'Jack' print(classmates) # ==> ['Michael', 'Bob', 'Tracy']
替换元素 直接通过索引赋值,就可以替换掉原来的元素。
classmates[1] = 'Sarah' # 把 'Bob' 换成 'Sarah'
print(classmates)
# ==> ['Michael', 'Sarah', 'Tracy']4. 购物篮的多样性
列表非常包容,可以装不同类型的数据,甚至可以“娃套娃”,在列表里装另一个列表!
# 混合数据类型
L = ['Apple', 123, True]
# 列表里套列表
s = ['python', 'java', ['asp', 'php'], 'scheme']
print(len(s))
# ==> 4要取出 s 列表中的 'php',我们需要先找到 'php' 所在的列表 ['asp', 'php'](索引为 2),然后再从这个小列表中找到 'php'(索引为 1)。
print(s[2][1])
# ==> 'php'📦 Tuple (元组):不可变的密封礼盒
元组和列表非常像,也是一个有序的容器。但它有一个核心特点:一旦创建,就不能修改。就像一个出厂时就密封好的礼盒,你只能看,不能增删或替换里面的礼物。
classmates = ('Michael', 'Bob', 'Tracy')它没有 append()、insert() 或 pop() 这些方法。你也不能通过 classmates[1] = 'Sarah' 来修改元素。
🤔 为什么要用元组? 因为不可变,所以元组的数据更安全,在多线程等复杂场景下能避免意外的修改。程序的逻辑也更清晰。原则是:如果一个集合的数据不需要被修改,那就尽量使用元组。
元组的创建陷阱 ⚠️
创建元组时,有两个小“陷阱”需要特别注意。
陷阱1:定义只有一个元素的元组 如果你想创建一个只有一个元素的元组,下面的写法是错误的:
# 错误!这会被当成是数字 1,而不是元组
t = (1)
print(t)
# ==> 1这是因为 () 也被用在数学运算中,Python 会优先把它当成数学括号来计算。
✅ 正确的写法是:必须在唯一的元素后面加上一个逗号 ,
t = (1,)
print(t)
# ==> (1,)这个逗号就是用来消除歧义,告诉 Python:“我正在创建一个元组!”
陷阱2:“可变的”元组 来看一个神奇的例子:
t = ('a', 'b', ['A', 'B'])这个元组里包含了一个列表。我们试试修改那个列表:
t[2][0] = 'X' # 把列表的第一个元素 'A' 改成 'X'
t[2][1] = 'Y' # 把列表的第二个元素 'B' 改成 'Y'
print(t)
# ==> ('a', 'b', ['X', 'Y'])咦?不是说元组不可变吗,怎么它的内容变了?
解密: 元组的“不可变”指的是元组中每个元素所指向的东西是不可变的。
元素
'a'指向了字符串'a',这个指向不能变。元素
['A', 'B']指向了一个列表对象,这个指向也不能变。你不能让t[2]去指向另一个完全不同的列表。
但是,那个列表对象本身是可变的!我们修改的是列表内部的元素,而元组 t 包含的那个指向列表的“地址”从未改变。
可以这样理解: 你有一个写着朋友住址的便签(元组),这个住址是不能改的(不可变)。但你朋友可以重新装修他的房子(列表内容可变),甚至搬进来新的家庭成员。你手上的住址便签依然有效,它指向的还是那个房子。
总结一下:
List (列表):灵活,可变,像购物篮。用
[ ]定义。Tuple (元组):安全,不可
Part 1: 神秘的元组 (Tuple) 到底是什么?
简单来说,元组就是一个装东西的容器,和列表很像,但它有一个非常重要的特点:不可变 (Immutable)。
你可以把列表想象成一个可以随时增删物品的购物篮,而元组则像是一个出厂时就封装好的礼盒,一旦封装好,里面的东西就不能再改变了。
如何创建元组?
这里有几种常见的方法,我们来一一分解。
A. 创建包含多个元素的元组(最常见)
这是最标准的方式,用小括号 () 把用逗号 , 分隔的元素包起来。
# 一个包含公司名字的元组
companies = ('Apple', 'Google', 'Microsoft')
# 一个包含不同数据类型的元组
mixed_tuple = (1, 'Hello', 3.14)
print(companies)
print(mixed_tuple)B. 创建空元组
有时候你需要一个空的容器作为起点,非常简单:
empty_tuple = ()
print(empty_tuple)C. 创建只有一个元素的元组 (⚠️ 小白最易犯错点!)
这是我们之前讨论的重点,也是新手最容易困惑的地方。
✅ 正确方式:必须加逗号!
# 正确!数字 2 后面有一个逗号
single_element_tuple = (2,)
print(single_element_tuple)
print(type(single_element_tuple)) # type() 函数可以查看变量的类型输出结果会告诉你这是一个 <class 'tuple'>。
❌ 错误方式:不加逗号
# 错误!这只是一个普通的数字
not_a_tuple = (2)
print(not_a_tuple)
print(type(not_a_tuple))输出结果会显示这是一个 <class 'int'>,也就是一个整数!
为什么呢? 因为 Python 里的 () 也被用来控制数学运算的优先级(比如 (2 + 3) * 4)。为了区分 "一个元素的元组" 和 "一个被括号包起来的数字",Python 规定,单元素元组必须在元素后面加一个逗号。这个逗号就是告诉 Python:“嘿,我正在创建一个元组!”
Part 2: 像 GPS 一样精确定位:列表索引
索引 (Index) 就是数据在列表或元组中的“门牌号”或“座位号”。通过这个号码,我们可以精确地找到任何一个元素。
最重要的规则:索引永远从 0 开始!
A. 简单列表的索引
我们先看一个简单的例子。
fruits = ['苹果', '香蕉', '樱桃']
# 索引: 0 1 2想得到
'苹果'?它的门牌号是0->fruits[0]想得到
'樱桃'?它的门牌号是2->fruits[2]
B. 嵌套列表的索引 (进阶)
这就是我们之前遇到的问题。当一个列表里面装着其他列表时,我们就需要用“多层门牌号”来定位。
让我们回到那个例子:
L = [
['Apple', 'Google', 'Microsoft'], # 这是第 0 号列表
['Java', 'Python', 'Ruby', 'PHP'], # 这是第 1 号列表
['Adam', 'Bart', 'Bob'] # 这是第 2 号列表
]🎯 我们的目标是:打印 Apple
我们可以分两步走,就像导航一样:
第一步:找到
Apple所在的街道(小列表)。 'Apple' 在第一个小列表['Apple', 'Google', 'Microsoft']中。这个小列表在L中的门牌号是0。 所以,我们用L[0]来锁定这条“街道”。# L[0] 的结果是 ['Apple', 'Google', 'Microsoft']第二步:在这条街道上找到
Apple的门牌号。 现在我们已经拿到了['Apple', 'Google', 'Microsoft']这个列表。在这个新列表里,Apple是第一个元素,所以它的门牌号是0。
最后,把两步合在一起:
我们先用 L[0] 定位到第一个列表,然后再用 [0] 定位到这个列表里的第一个元素。
# 打印 Apple:
print(L[0][0]) 这就完成了!L[0][0] 就像一个精确的坐标,告诉 Python 去 0 号列表里,拿出 0 号元素。
总结
恭喜你!现在你已经掌握了:
元组是不可变的。
创建元组时,最要小心的是单元素元组,别忘了那个神奇的逗号
(item,)。索引是元素的地址,永远从
0开始。对于嵌套列表,使用
[ ] [ ]这样的多重索引来层层深入,精确定位。
继续练习,你会越来越熟练的!