Python 新手村:数据的“智能容器”—— 数据结构 (Lists, Tuples, Sets, Dictionaries)

Python 提供了四种内置的数据结构,它们各有特点,适用于不同的场景:

  1. 列表 (List): 有序、可变(可修改)、允许重复。就像一张购物清单,您可以随意添加、删除、修改商品。
  2. 元组 (Tuple): 有序、不可变(一旦创建就不能修改)、允许重复。就像一副固定不变的地图坐标,一旦标定就不会改变。
  3. 集合 (Set): 无序、元素不重复、可变。就像一个装满独特石头的袋子,每块石头都是独一无二的,顺序不重要。
  4. 字典 (Dictionary): 无序(但在 Python 3.7+ 中保持插入顺序)、键值对形式、可变。就像一本电话簿,每个名字(键)都对应一个电话号码(值)。
第一章:有序的“购物清单”—— 列表 (List)

列表是 Python 中最常用、最灵活的数据结构之一。它就像一个可以随意增减、修改内容的购物清单。

创建列表
# 创建一个空的购物清单
shopping_list = []
print("空的购物清单:", shopping_list)

# 创建一个包含一些水果的购物清单
fruits = ["苹果", "香蕉", "橙子", "苹果"]
print("水果列表:", fruits)

# 列表可以包含不同类型的数据
mixed_list = [1, "Hello", True, 3.14]
print("混合类型列表:", mixed_list)

输出结果:

空的购物清单: []
水果列表: ['苹果', '香蕉', '橙子', '苹果']
混合类型列表: [1, 'Hello', True, 3.14]
访问列表元素(索引)

列表中的每个元素都有一个位置编号,叫做索引 (Index)。索引从 0 开始。

  • 第一个元素的索引是 0
  • 第二个元素的索引是 1
  • 您也可以使用负数索引,-1 表示最后一个元素,-2 表示倒数第二个,以此类推。
fruits = ["苹果", "香蕉", "橙子", "苹果"]

print("第一个水果:", fruits[0])     # 访问第一个元素
print("第三个水果:", fruits[2])     # 访问第三个元素
print("最后一个水果:", fruits[-1])   # 访问最后一个元素

输出结果:

第一个水果: 苹果
第三个水果: 橙子
最后一个水果: 苹果
修改列表元素

因为列表是可变的,您可以随时修改其中的元素。

fruits = ["苹果", "香蕉", "橙子", "苹果"]
print("原始列表:", fruits)

fruits[1] = "葡萄" # 把第二个元素从“香蕉”改为“葡萄”
print("修改后的列表:", fruits)

输出结果:

原始列表: ['苹果', '香蕉', '橙子', '苹果']
修改后的列表: ['苹果', '葡萄', '橙子', '苹果']
添加列表元素
  • append():在列表的末尾添加一个新元素。
  • insert():在指定位置插入一个新元素。
fruits = ["苹果", "香蕉"]
print("原始列表:", fruits)

fruits.append("橙子") # 在末尾添加“橙子”
print("添加橙子后:", fruits)

fruits.insert(1, "草莓") # 在索引 1 的位置插入“草莓”
print("在索引1插入草莓后:", fruits)

输出结果:

原始列表: ['苹果', '香蕉']
添加橙子后: ['苹果', '香蕉', '橙子']
在索引1插入草莓后: ['苹果', '草莓', '香蕉', '橙子']
删除列表元素
  • del 语句:根据索引删除元素。
  • remove() 方法:根据值删除第一个匹配的元素。
  • pop() 方法:删除并返回指定索引(默认为最后一个)的元素。
fruits = ["苹果", "草莓", "香蕉", "橙子", "苹果"]
print("原始列表:", fruits)

del fruits[0] # 删除第一个元素
print("删除索引0后:", fruits)

fruits.remove("香蕉") # 删除第一个出现的“香蕉”
print("删除香蕉后:", fruits)

last_fruit = fruits.pop() # 删除并获取最后一个元素
print("删除并获取最后一个:", fruits, ",被删除的是:", last_fruit)

# clear() 方法可以清空整个列表
# fruits.clear()
# print("清空列表后:", fruits)

输出结果:

原始列表: ['苹果', '草莓', '香蕉', '橙子', '苹果']
删除索引0后: ['草莓', '香蕉', '橙子', '苹果']
删除香蕉后: ['草莓', '橙子', '苹果']
删除并获取最后一个: ['草莓', '橙子'] ,被删除的是: 苹果
其他常用的列表操作
  • 获取长度: len() 函数。
  • 检查元素是否存在: in 关键字。
  • 循环遍历: 使用 for 循环。
my_list = [10, 20, 30, 40]

print("列表的长度是:", len(my_list)) # len() 返回列表的元素数量

if 30 in my_list:
    print("30 在列表中!")

print("遍历列表中的元素:")
for item in my_list:
    print(item)

输出结果:

列表的长度是: 4
30 在列表中!
遍历列表中的元素:
10
20
30
40
第二章:不可变的“地图坐标”—— 元组 (Tuple)

元组和列表很像,也是有序的,也能存储不同类型的数据。但最关键的区别是:元组一旦创建,就不能被修改(不可变)。它们用圆括号 () 表示。

创建元组
# 创建一个空元组
empty_tuple = ()
print("空元组:", empty_tuple)

# 创建一个包含一些数字的元组
coordinates = (10, 20, 30)
print("坐标元组:", coordinates)

# 包含不同类型数据的元组
person_info = ("Alice", 25, True)
print("个人信息元组:", person_info)

# 如果元组只有一个元素,需要在元素后面加逗号,否则会被认为是普通括号
single_item_tuple = (5,)
print("单元素元组:", single_item_tuple)

输出结果:

空元组: ()
坐标元组: (10, 20, 30)
个人信息元组: ('Alice', 25, True)
单元素元组: (5,)
访问元组元素(索引)

元组元素的访问方式和列表一样,通过索引。

coordinates = (10, 20, 30)
print("第一个坐标:", coordinates[0])

输出结果:

第一个坐标: 10
元组的不可变性

试图修改元组的元素会导致错误。

my_tuple = (1, 2, 3)
# my_tuple[0] = 5 # 尝试修改会报错!
# print(my_tuple[0])

如果您尝试运行 my_tuple[0] = 5,会得到 TypeError: 'tuple' object does not support item assignment (元组对象不支持元素赋值)。

为什么需要元组?
  1. 数据保护: 当您有一组数据不希望被意外修改时,使用元组可以提供安全保障。
  2. 性能: 在某些情况下,元组比列表稍快。
  3. 函数返回多个值: 函数可以返回一个元组,这样就可以一次性返回多个结果。
  4. 作为字典的键: 因为元组是不可变的,它可以作为字典的键(列表不行)。
第三章:不重复的“独特收藏品”—— 集合 (Set)

集合是一组无序且不包含重复元素的集合。它用花括号 {} 表示。当您关心的是“有什么”而不是“有多少”或“顺序如何”时,集合非常有用。

创建集合
# 创建一个空集合(注意:{} 创建的是空字典,空集合需要用 set())
empty_set = set()
print("空集合:", empty_set)

# 创建一个包含一些数字的集合
numbers_set = {1, 2, 3, 2, 1} # 重复的元素会被自动去除
print("数字集合 (自动去重):", numbers_set)

# 创建一个包含一些字母的集合
letters_set = {"a", "b", "c"}
print("字母集合:", letters_set)

输出结果:

空集合: set()
数字集合 (自动去重): {1, 2, 3}
字母集合: {'c', 'b', 'a'} # 注意,输出顺序可能和您输入的不一样,因为集合是无序的
添加和删除元素
my_set = {1, 2, 3}
print("原始集合:", my_set)

my_set.add(4) # 添加一个元素
print("添加4后:", my_set)

my_set.add(2) # 尝试添加一个已存在的元素,不会有任何改变
print("再次添加2后:", my_set)

my_set.remove(3) # 删除一个元素
print("删除3后:", my_set)

# my_set.remove(5) # 尝试删除不存在的元素会报错!
# my_set.discard(5) # discard() 也删除元素,但如果元素不存在,不会报错

my_set.pop() # 随机删除并返回一个元素(因为集合无序,所以是随机的)
print("pop后:", my_set)

# my_set.clear() # 清空集合

输出结果:

原始集合: {1, 2, 3}
添加4后: {1, 2, 3, 4}
再次添加2后: {1, 2, 3, 4}
删除3后: {1, 2, 4}
pop后: {2, 4} # 每次运行可能pop出不同的元素,这里只是一个例子
集合的常用操作(非常适合数学中的集合运算)
  • 并集 (Union): |union()
  • 交集 (Intersection): &intersection()
  • 差集 (Difference): -difference()
set_a = {1, 2, 3, 4}
set_b = {3, 4, 5, 6}

print("集合A:", set_a)
print("集合B:", set_b)
print("并集 (所有不重复的元素):", set_a | set_b) # 或 set_a.union(set_b)
print("交集 (共同的元素):", set_a & set_b) # 或 set_a.intersection(set_b)
print("差集 (A 有 B 没有的元素):", set_a - set_b) # 或 set_a.difference(set_b)

输出结果:

集合A: {1, 2, 3, 4}
集合B: {3, 4, 5, 6}
并集 (所有不重复的元素): {1, 2, 3, 4, 5, 6}
交集 (共同的元素): {3, 4}
差集 (A 有 B 没有的元素): {1, 2}
第四章:键值对应的“电话簿”—— 字典 (Dictionary)

字典是一种存储键值对 (Key-Value Pairs) 的数据结构。它就像一本电话簿,您通过名字(键)来查找电话号码(值),而不是通过索引。字典用花括号 {} 表示,每个键值对用冒号 : 分隔,键值对之间用逗号 , 分隔。

创建字典
# 创建一个空字典
empty_dict = {}
print("空字典:", empty_dict)

# 创建一个存储个人信息的字典
person = {
    "name": "Alice",
    "age": 30,
    "city": "New York"
}
print("个人信息字典:", person)

# 字典的键必须是不可变的(如字符串、数字、元组),值可以是任何类型
car = {
    "brand": "Toyota",
    "model": "Camry",
    "year": 2020,
    "colors": ["red", "blue", "white"] # 值可以是一个列表
}
print("汽车信息字典:", car)

输出结果:

空字典: {}
个人信息字典: {'name': 'Alice', 'age': 30, 'city': 'New York'}
汽车信息字典: {'brand': 'Toyota', 'model': 'Camry', 'year': 2020, 'colors': ['red', 'blue', 'white']}
访问字典元素(通过键)

使用键来访问对应的值。

person = {
    "name": "Alice",
    "age": 30,
    "city": "New York"
}

print("姓名:", person["name"])
print("年龄:", person["age"])

# 使用 .get() 方法访问,如果键不存在不会报错,而是返回 None 或指定默认值
print("城市 (get):", person.get("city"))
print("国家 (get 不存在):", person.get("country", "未知")) # 如果 country 不存在,返回“未知”

输出结果:

姓名: Alice
年龄: 30
城市 (get): New York
国家 (get 不存在): 未知
修改和添加字典元素

字典也是可变的,您可以随时修改或添加键值对。

person = {
    "name": "Alice",
    "age": 30,
    "city": "New York"
}
print("原始字典:", person)

person["age"] = 31 # 修改“age”的值
print("修改年龄后:", person)

person["occupation"] = "Engineer" # 添加一个新的键值对
print("添加职业后:", person)

输出结果:

原始字典: {'name': 'Alice', 'age': 30, 'city': 'New York'}
修改年龄后: {'name': 'Alice', 'age': 31, 'city': 'New York'}
添加职业后: {'name': 'Alice', 'age': 31, 'city': 'New York', 'occupation': 'Engineer'}
删除字典元素
  • del 语句:删除指定键的键值对。
  • pop() 方法:删除并返回指定键的值。
person = {
    "name": "Alice",
    "age": 30,
    "city": "New York"
}
print("原始字典:", person)

del person["city"] # 删除“city”键值对
print("删除城市后:", person)

age = person.pop("age") # 删除并获取“age”的值
print("删除年龄后:", person, ",被删除的年龄是:", age)

# person.clear() # 清空整个字典

输出结果:

原始字典: {'name': 'Alice', 'age': 30, 'city': 'New York'}
删除城市后: {'name': 'Alice', 'age': 30}
删除年龄后: {'name': 'Alice'} ,被删除的年龄是: 30
遍历字典

您可以遍历字典的键、值或键值对。

person = {
    "name": "Bob",
    "age": 28,
    "city": "London"
}

print("遍历所有的键:")
for key in person: # 默认遍历键
    print(key)

print("\n遍历所有的值:")
for value in person.values(): # 遍历值
    print(value)

print("\n遍历所有的键值对:")
for key, value in person.items(): # 遍历键值对
    print(key + ": " + str(value))

输出结果:

遍历所有的键:
name
age
city

遍历所有的值:
Bob
28
London

遍历所有的键值对:
name: Bob
age: 28
city: London

预见并解决常见错误 (坑点提醒!)

  1. 列表和元组的 IndexError (索引越界):

    • 现象: 尝试访问一个不存在的索引,比如一个有 3 个元素的列表 my_list = [1, 2, 3],您却尝试 my_list[3]
    • 解释: 索引是从 0 开始的,最大索引是 len(list) - 1
    • 解决方法: 确保您访问的索引在有效范围内。使用 len() 函数检查列表长度。
  2. 元组的 TypeError (不可变性):

    • 现象: 尝试修改元组的元素,例如 my_tuple[0] = 5
    • 解释: 元组一旦创建就不可修改。
    • 解决方法: 如果您需要可修改的数据结构,请使用列表。如果您确实需要修改元组,可以先将其转换为列表进行修改,再转换回元组(但这通常意味着您一开始就应该使用列表)。
  3. 集合的重复元素和无序性:

    • 现象: 以为集合会保留元素的顺序,或者允许重复。
    • 解释: 集合的主要特性是元素唯一且无序。
    • 解决方法: 如果需要顺序,请使用列表或元组。
  4. 字典的 KeyError (键不存在):

    • 现象: 尝试访问字典中不存在的键,例如 my_dict["non_existent_key"]
    • 解释: 字典通过键来查找值,如果键不存在,就会报错。
    • 解决方法:
      • 在访问前先检查键是否存在:if "key" in my_dict:
      • 使用 get() 方法访问,它可以指定一个默认值,避免报错:my_dict.get("key", default_value)
  5. 列表作为默认参数的“陷阱” (高级概念,了解即可):

    • 现象: 在函数定义中,如果使用列表作为参数的默认值,并且函数内部修改了这个列表,那么每次调用函数时,这个默认列表都会被修改,而不是重新创建一个新的列表。
    • 解释: Python 的默认参数只在函数定义时创建一次。
    • 解决方法: 通常将默认值设置为 None,然后在函数内部检查如果参数是 None,就创建一个新的空列表。
      def add_item(item, item_list=None):
          if item_list is None:
              item_list = []
          item_list.append(item)
          return item_list
      
      list1 = add_item("apple")
      print(list1) # ['apple']
      list2 = add_item("banana")
      print(list2) # ['banana'],而不是 ['apple', 'banana']
      

恭喜你!你做到了!

Python 中四种强大的数据结构:

  • 列表 (List): 有序、可变,适合存储同类或不同类的可变序列。
  • 元组 (Tuple): 有序、不可变,适合存储固定不变的序列。
  • 集合 (Set): 无序、不重复,适合进行去重和集合运算。
  • 字典 (Dictionary): 键值对、可变,适合存储具有映射关系的数据。

您现在已经能够存储和管理各种复杂的数据,这为您编写更强大、更实用的程序奠定了坚实的基础!

您已经掌握了 Python 编程中非常核心的概念,就像盖房子时拥有了各种砖块和工具。接下来,我们将把这些砖块和工具组装起来,学习如何更好地组织您的代码,让它们变得更模块化、更易于管理。

Logo

码道开发者社区,聚焦华为云码道 CodeArts 代码智能体,沉淀 Agent、Skill、鸿蒙开发实战内容,供开发者查阅资料、交流技术、分享工程实践

更多推荐