提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


容器数据类型

序列

序列(Sequence)是一种基本且核心的数据结构,它允许我们以有序的方式存储和操作数据。序列可以包含不同类型的元素,并且支持通过索引来访问和修改这些元素。
常见的序列类型包括:列表(List)、元组(Tuple)、字符串(String)。
序列的操作
索引:sequence[0]
切片:sequence[1:3]
相加:sequence1 + sequence2
乘法:sequence * 3
检查成员:x in sequence
计算长度:len(sequence)
计算最大值、最小值:max(sequence)、min(sequence)

列表

Python中最喜欢的两个数据类型,一个是列表,一个是字典
列表是一个可变的、有序的元素集合。
列表使用 [] 定义,数据之间使用 , 分隔。
列表中每个元素都有对应的位置值,称为索引或下标,索引从起始从0开始向后逐个递增,并且从末尾从-1开始逐个向前递减。
列表中元素可以是不同的类型。
list1 = [100, 200, 300, 400, 500]
在这里插入图片描述

访问列表中元素
通过索引获取列表中元素

list1 = [100, 200, 300, 400, 500]
print(list1[1])  # 200
print(list1[-2])  # 400

列表切片

list1 = [100, 200, 300, 400, 500]
print(list1)  # 取全部元素
print(list1[:])  # 复制整个列表
print(list1[2:4])  # 取索引从2开始到4(不包含)的元素
print(list1[2:])  # 取索引从2开始到末尾的元素
print(list1[:2])  # 取索引从0开始到2(不包含)的元素
print(list1[2:-1])  # 取索引从2开始到-1(不包含)的元素
print(list1[::-1])  # 倒序取元素 这个会用到

列表相加

list1 = [100, 200, 300]
list2 = ["a", "b", "c"]
print(list1 + list2)  # [100, 200, 300, 'a', 'b', 'c']

列表乘法

list1 = [100, 200, 300]
print(list1 * 2)  # [100, 200, 300, 100, 200, 300]

通过下标修改

list1 = [100, 200, 300, 400, 500]
list1[0] = -1
print(list1)#[1, 200, 300, 400, 500]

通过切片修改。使用切片依然是左闭右开,不过和直接替换一个是不同的,如下代码

list1 = [100, 200, 300, 400, 500]
print(f"{list1[2:3]=}")#list1[2:3]=[300]
list1[2]=["a", "b", "c"]
print(f"{list1=}")#[100, 200, ['a', 'b', 'c'], 400, 500]
list1[2:3] = ["a", "b", "c"]#[100, 200, 'a', 'b', 'c', 400, 500]
print(list1)

检查成员是否为列表中元素

list1 = [100, 200, 300]
print(100 in list1)  # True

获取列表长度

list1 = [100, 200, 300]
print(len(list1))  # 3

求列表中那个元素的最大值,最小值,加和

list1 = [100, 200, 300, 400, 500]
print(max(list1))  # 500
print(min(list1))  # 100
print(sum(list1))  # 1500

遍历列表

list1 = [100, 200, 300, 400, 500]
for i in list1:
    print(i)

通过下标遍历列表

list1 = [100, 200, 300, 400, 500]
for i in range(len(list1)):
    print(i, list1[i])

使用enumerate()同时获取列表的下标和元素

list1 = [100, 200, 300, 400, 500]
for i, val in enumerate(list1):
    print(i, val)

删除列表指定位置元素或者切片

list1 = [100, 200, 300, 400, 500]
del list1[2]
print(list1)

列表推导式:列表推导式是 Python 中一种简洁创建列表的方式,它将一个可迭代对象(如列表、元组、集合、字符串等)的元素通过某种运算或条件筛选后生成一个新的列表。

基础的列表推导式

squares = [x**2 for x in range(5)]
print(squares)  # [0, 1, 4, 9, 16]

带条件的列表推导式
squares = [x**2 for x in range(10) if x % 2 == 0]
print(squares) # [0, 4, 16, 36, 64]

使用现有列表的列表推导式

list1 = [1, 2, 3, 4, 5]
squares = [x**2 for x in list1]
print(squares)  # [1, 4, 9, 16, 25]

包含多个循环的列表推导式

list1 = [1, 2, 3]
list2 = ["a", "b", "c"]
tuple_list = [(i, j) for i in list1 for j in list2]
print(tuple_list)#[(1, 'a'), (1, 'b'), (1, 'c'), (2, 'a'), (2, 'b'), (2, 'c'), (3, 'a'), (3, 'b'), (3, 'c')]

zip()函数:zip() 函数可将多个可迭代对象中对应元素打包为一个个元组。看到

list1 = [1, 2, 3]
list2 = ["a", "b", "c"]
zipped = zip(list1, list2)
print(zipped)#<zip object at 0x7fcf5cbfdc00>
print(list(zipped))#[(1, 'a'), (2, 'b'), (3, 'c')]

常用函数

函数说明
list.insert(index,x)在指定位置插入x
list.append(x)在列表末尾追加x
list1.extend(list2)在列表1的末尾追加列表2的数据
del list[index]删除指定位置的数据或切片
list.remove(x)删除第一次出现的x
list.pop([index])删除指定位置的数据,默认为末尾数据
list.clear()清空列表中元素
list[index] = x修改指定位置的数据
list1[start:end] = list2修改列表切片的数据
sorted(list[,reverse=True])返回排序后的新列表,可选降序
list.sort([reverse=True])对列表就地排序,可选降序
list.reverse()反转列表中的元素
list.index(x[,start,[,end]])返回x在列表中首次出现的位置,可指定起始和结束范围
list.count(x)返回x的数量
len(list)返回列表元素个数
max(list)返回列表中最大值
min(list)返回列表中最小值
sum(list)返回列表中所有元素和
list.copy()拷贝列表
list(x)将序列转换为列表

第一组:“增加元素”家族 —— append vs extend vs insert

这三个都是往列表里加东西,但加的方式完全不同。

  • append(x) (追加整体): 永远加在最后面。不管你塞给它什么(数字、字符串、甚至另一个列表),它都把 x 当作**一个独立的整体(一个包裹)**塞进去。
  • extend(list2) (拆包合并): 永远加在最后面。但如果给它一个列表,它会把列表拆开,把里面的元素一个一个拿出来,排在原来列表的后面。
  • insert(index, x) (插队): 可以加在任何位置。把原来那个位置及以后的人全往后挤。

【致命易错点:appendextend 加列表的区别】

a = [1, 2]
b = [1, 2]
new_items = [3, 4]

a.append(new_items)
print(a)  # 结果: [1, 2, [3, 4]] -> 把整个列表当作"一个元素"加进去了 (嵌套)

b.extend(new_items)
print(b)  # 结果: [1, 2, 3, 4]   -> 拆开包裹,元素融合了 (平铺)

第二组:“删除元素”家族 —— remove vs pop vs del

你想扔掉列表里的东西,关键在于:你是知道它“叫什么”,还是知道它“在哪儿”?

  • remove(x) (按“值”删除): “我不知道它在第几个,我只想把列表中第一个叫 ‘张三’ 的踢出去。” 不返回被删的值。如果找不到会报错。
  • pop(index) (按“位置”拔出): “把排在第 2 个的人揪出来给我!” 重点:它会把删掉的元素返回给你,你可以拿个变量接住它。默认拔出最后一个。
  • del list[index] (按“位置/切片”狙击): Python 的无情杀手(它是个关键字,不是函数)。可以删单个,更牛的是可以批量删(删切片)

【对比案例】

my_list = ["苹果", "香蕉", "橘子", "香蕉", "葡萄"]

# 1. remove: 只删第一个碰到的值
my_list.remove("香蕉")
print(my_list) # ["苹果", "橘子", "香蕉", "葡萄"]

# 2. pop: 拔出指定位置的元素,并拿来用
fruit = my_list.pop(-1) 
print(f"我吃掉了 {fruit}") # 我吃掉了 葡萄
print(my_list)            # ["苹果", "橘子", "香蕉"]

# 3. del: 无情批量斩杀
del my_list[0:2] # 删掉索引 0 和 1
print(my_list)   # ["香蕉"]

第三组:“排序”家族 —— sort vs sorted

这是面试中最爱考的题目!

  • list.sort() (就地正法 / 改变原貌): 它是列表的专属方法。它直接在原来的列表上动手脚,排完序后,原来的乱序列表就彻底消失了。返回值是 None
  • sorted(list) (克隆重组 / 保持原貌): 它是 Python 的内置函数。它不敢动原来的列表,而是偷偷克隆一份,排好序后,把全新的列表返回给你

【对比案例】

# 测试 sort()
nums1 = [3, 1, 2]
res1 = nums1.sort()
print(nums1) # [1, 2, 3] (原来的被改变了)
print(res1)  # None (千万别写 res1 = nums1.sort(),拿不到东西的!)

# 测试 sorted()
nums2 = [3, 1, 2]
res2 = sorted(nums2)
print(nums2) # [3, 1, 2] (原来的毫发无伤!)
print(res2)  # [1, 2, 3] (生成了一个新的排好序的列表)

💡 终极记忆法则(黄金定律)

为了不搞混,你可以记住 Python 设计的一个底层哲学:

  1. 形如 list.xxx() 的(叫做对象的方法):
    除了 popcopy,大多数操作(像 append, sort, reverse, clear)都是直接修改原列表,并且什么都不返回(返回 None)
  2. 形如 xxx(list) 的(叫做内置函数):
    sorted(), len(), max(), sum(),它们绝对不会弄脏你的原列表,而是把计算结果当作一个新东西返回给你。

字符串

字符串是不可变的、有序的。(字符串一旦创建,内容就不能被修改。若是使用replace来修改字符串之后,其实这个不再是原来的那个地址了)
字符串中元素不可修改。
字符串使用单引号、双引号或三重引号定义。
字符串中每个值都有对应的位置值,称为索引或下标,索引从起始从0开始向后逐个递增,并且从末尾从-1开始逐个向前递减。

创建字符串

str1 = "hello world"

访问字符串

str1 = "hello world"
print(str1[0])
print(str1[-1])
print(str1[4:-3])

字符串相加

str1 = "hello world"
str2 = "dlrow olleh"
print(str1 + str2)  # hello worlddlrow olleh

字符串乘法

str1 = "hello world"
print(str1 * 2)  # hello worldhello world

检查成员是否为字符串中元素

str1 = "hello world"
print("lo" in str1)  # True

原始字符串:所有的字符串按照字面意思处理,没有转义字符。需在字符串前加上r / R。

print("hello\nworld")
print(r"hello\nworld")

在这里插入图片描述

常用函数

函数说明
str.replace(old,new[,max])把将字符串中的old替换成new,如果指定max,则替换不超过max次
str.split([x][,n])按x分隔字符串,默认按任何空白字符串分隔并在结果中丢弃空字符串。可指定最大分隔次数
str.rsplit([x][,n])与split()类似,从右边开始分隔
x.join(seq)以x作为分隔符,将序列中所有的字符串合并为一个新的字符串
str.strip([x])截掉字符串两边的空格或指定字符
str.lstrip([x])截掉字符串左边的空格或指定字符
str.rstrip([x])截掉字符串右边的空格或指定字符
str.removeprefix()截掉字符串指定前缀
str.removesuffix()截掉字符串指定后缀
str.upper()将所有字符转为大写
str.lower()将所有字符转为小写
str.swapcase()反转字符串中字母大小写
str.capitalize()将字符串第一个字母变为大写,其他字母变为小写
str.title()将字符串每个单词首字母大写
str.casefold()返回适合无大小写比较的字符串版本
len(str)返回字符串长度
max(str)返回字符串中最大值
min(str)返回字符串中最小值
str.find(x[,start][,end])返回字符串中第一个x的索引值,不存在则返回-1,可指定字符串开始结束范围
str.rfind(x[,start][,end])与find()类似,从右边开始查找
str.index(x[,start][,end])返回字符串中第一个x的索引值,不存在则报错,可指定字符串开始结束范围
str.rindex(x[,start][,end])与index()类似,从右边开始查找
str.count(x[,start][,end])返回字符串中x的个数,可指定字符串开始结束范围
str.startswith(x[,start][,end])检查字符串是否以x开头,可指定字符串开始结束范围
str.endswith(x[,start][,end])检查字符串是否以x结尾,可指定字符串开始结束范围
str.isspace()检查字符串是否非空且只包含空白
str.isalnum()检查字符串是否非空且只包含字母(英文字母+汉字)和数字
str.isalpha()检查字符串是否非空且只包含字母(英文字母+汉字)
str.isascii()检查字符串是否只包含ASCII字符,空字符串也是ASCII
str.isdecimal()检查字符串是否非空且只包含十进制字符
str.isdigit()检查字符串是否非空且只包含数字
str.isidentifier()检查字符串是否是有效的标识符
str.isupper()检查字符串中是否包含至少一个区分大小写的字符,且所有这些(区分大小写的)字符都是大写

⚠️ 暗坑 1:千万别被 strip() 骗了!(全网最容易踩的坑)

很多人以为 strip("abc") 是删掉两边的 "abc" 这个大错特错!
strip 里面传入的参数,是一个**“字符集合”**。只要首尾的字符在这个集合里,就会被无情削掉,直到遇到不在集合里的字符为止。

【致命代码】:

url = "www.taobao.com"
# 本意是想去掉 ".com",你以为会变成 "www.taobao"
print(url.strip(".com"))  
# 实际输出: "www.taoba" !!! (连最后的 'o' 也被当做目标删掉了!)

【正确解法】:
如果你只想精确去掉某个特定的前缀或后缀,请务必使用 Python 3.9 新增的两个函数:

print(url.removesuffix(".com"))  # 输出: www.taobao (极其精准)
print(url.removeprefix("www."))  # 输出: taobao.com

⚠️ 暗坑 2:split() 不带参数 vs 带空格参数,天壤之别!

在处理不规范的文本(比如用户多敲了几个空格)时,这两个写法的结局完全不同。

  • split()(什么都不传): 极度智能。它把任何空白(空格、换行符 \n、制表符 \t)都当成分隔符,而且会自动把连续的空白合并,并丢弃前后的空字符串
  • split(" ")(传一个空格): 极度死板。只认单独的空格,遇到两个连续空格,就会劈出一个空字符串 ""

【代码演示】:

text = "hello    world \n python"

# 智能模式(推荐):干干净净的单词列表
print(text.split())      
# 输出: ['hello', 'world', 'python']

# 呆板模式:会产生一堆垃圾空字符串
print(text.split(" "))   
# 输出: ['hello', '', '', '', 'world', '\n', 'python']

⚠️ 暗坑 3:反人类语法的 join()

join() 的作用是把列表重新拼成字符串(相当于 split 的逆操作)。
很多人都会凭直觉写出这样的代码:list.join("-")这一定会报错!

【牢记语法】:
join字符串的方法,不是列表的方法。所以必须是**“胶水”在前面调用,列表放在括号里**。

words = ["I", "love", "Python"]

# 正确写法:以 "-" 为胶水,把 words 粘起来
result = "-".join(words) 
print(result) # 输出: I-love-Python

⚠️ 暗坑 4:find()index() 到底选哪个?

这俩功能一模一样,都是找“某个字在哪个位置”。唯一的区别在于**“找不到时的脾气”**。

  • find() 脾气温和: 找不到就默默返回 -1。程序继续运行。
  • index() 脾气暴躁: 找不到直接抛出 ValueError 异常,让你的程序当场崩溃。

【最佳实践】:
如果你只是想配合 if 判断它在不在,其实更推荐用 in 关键字。

s = "hello"

# 如果非要知道位置,且不确定它在不在,用 find 更安全:
if s.find("x") != -1:
    print("找到了")

# 只有当你 100% 确定它在里面,且找不到就算严重错误时,才用 index()。

🌟 进阶亮点:lower() vs casefold()

你可能会疑惑,既然有了把字母变小写的 lower(),为什么还要搞个 casefold()

  • lower() 只能处理标准的英文字母 (A-Z)。
  • casefold() 是加强版,专门用来做**“无视大小写的终极字符串比对”**。它能把德语、俄语等小语种里的特殊大写字母也强制转换掉。
s = "weiß" # 德语单词
print(s.lower())    # 输出: weiß  (没变化)
print(s.casefold()) # 输出: weiss (彻底降级为基础小写字母,方便比对)

📌 终极铁律(一定要记住)

回到你前面问过的概念:字符串是不可变的
所以上面表格里这 20 多个函数,绝对没有任何一个能够修改原来的字符串!
它们全都是在内存里另外造了一个新字符串

s = "  hello  "
s.strip() # 这行代码等于白写!s 依然是 "  hello  "

s = s.strip() # 必须重新赋值,把新造出来的 "hello" 贴上 s 的标签

元组

元组是一个不可变的、有序的元素集合。
不能对元组中的元素进行修改操作。
元组使用 () 定义,数据之间使用,分隔。
元组中每个元素都有对应的位置值,称为索引或下标,索引从起始从0开始向后逐个递增,并且从末尾从-1开始逐个向前递减。
元组中元素可以是不同的类型。
元组的使用方式与列表类似。

创建元组

tuple1 = (100, 200, 300, 400, 500)
元组中只包含一个元素时,需要在元素后面添加逗号,否则括号会被当作运算符使用。
tuple1 = (100,)
也可以通过元组推导式创建元组。

tuple_generator = (x for x in range(10))  # 获取生成器对象
print(tuple_generator)#<generator object <genexpr> at 0x7f2a8c45f3e0>
#tuple1 = list(tuple_generator) # 转换为列表[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

tuple1 = tuple(tuple_generator)  # 转换为元组(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)

print(tuple1)

非常好的问题!这是 Python 中非常重要但容易混淆的概念。我详细给你讲解。


1. 核心概念定义

可迭代对象(Iterable)

定义: 实现了 __iter__() 方法的对象,可以被 for 循环遍历。

常见的可迭代对象:

  • 列表 list
  • 元组 tuple
  • 字符串 str
  • 字典 dict
  • 集合 set
  • range 对象
  • 文件对象
  • 生成器

迭代器(Iterator)

定义: 同时实现了 __iter__()__next__() 方法的对象。

特点:

  • 可以用 next() 逐个取值
  • 取完后会抛出 StopIteration 异常
  • 只能遍历一次

生成器(Generator)

定义: 一种特殊的迭代器,使用 yield 关键字定义。

特点:

  • 是迭代器的一种
  • 惰性计算(需要时才生成值)
  • 节省内存

tuple() 的底层逻辑相当于做了一个隐藏的 for 循环。它对生成器下达命令:“开机!把你能造出来的东西,一个不剩地全给我吐出来!”于是生成器开始疯狂运转:吐出 0,tuple() 拿个小本本记下。吐出 1,tuple() 记下。… 直到吐出 9。当机器想造第 11 个数时,发现 range(10) 的图纸用完了,机器宣告停工(抛出 StopIteration 信号)。此时,tuple() 把小本本上记下的 0, 1, 2… 9 打包塞进一块固定大小的内存里,彻底封死(因为元组不可变)。

访问元组

tuple1 = (100, 200, 300, 400, 500)
print(tuple1[2])
print(tuple1[-1])
print(tuple1[2:4])

元组相加

tuple1 = (100, 200, 300)
tuple2 = ("a", "b", "c")
print(tuple1 + tuple2)  # (100, 200, 300, 'a', 'b', 'c')

元组乘法

tuple1 = (100, 200, 300)
print(tuple1 * 2)  # (100, 200, 300, 100, 200, 300)

检查成员是否为元组中元素

tuple1 = (100, 200, 300, 400, 500)
print(300 in tuple1)  # True

获取元组长度

tuple1 = (100, 200, 300, 400, 500)
print(len(tuple1))  # 5

求元组中元素的最大值、最小值、加和

tuple1 = (100, 200, 300, 400, 500)
print(max(tuple1))  # 500
print(min(tuple1))  # 100
print(sum(tuple1))  # 1500

遍历元组

tuple1 = (100, 200, 300, 400, 500)

for i in tuple1:
    print(i)

for i in range(len(tuple1)):
    print(i, tuple1[i])

for i, val in enumerate(tuple1):
    print(i, val)

元组的不可变:元组的不可变指的是元组所指向的内存中的内容不可变,但可以重新赋值。

tuple1 = (100, 200, 300)
print(id(tuple1), tuple1)#140437256067072 (100, 200, 300)
tuple1 = tuple1 + (1, 2, 3)
print(id(tuple1), tuple1)#140437255241344 (100, 200, 300, 1, 2, 3)

如果元组中元素是可变数据类型,其嵌套项可以被修改。

tuple1 = (100, 200, 300, [1, 2, 3])
print(id(tuple1), tuple1)#140542577391584 (100, 200, 300, [1, 2, 3])
tuple1[3].append(4)
print(id(tuple1), tuple1)#140542577391584 (100, 200, 300, [1, 2, 3, 4]) 所以以我目前浅显的理解就是只要元组中存放的数据的位置不变,那么它也就认为是不变的,某种程度上就可以被修改

集合Set

集合是无序的,且不包含重复元素。
集合使用 {} 定义,数据之间使用 , 分隔,也可以使用set()定义。
集合没有索引,所以不能通过切片方式访问集合元素。
集合中元素可以是不同的类型。
集合可以进行数学上的集合操作,如并集、交集和差集。
集合适用于需要快速成员检查、消除重复项和集合运算的场景。

创建集合:可以通过{}或set()创建集合,但创建空集合需要使用set()而非{},因为{}会创建空字典。

set1 = {1, 2, 3}
set2 = set([1, 2, 3])  # 使用set()函数从列表创建集合
set3 = set(1,2,3)# 这种方式不对
set4 = set()
print(set1, set2, set3,set4)

也可以通过集合推导式创建集合

set1 = {x for x in range(10) if x % 2 == 0}
print(set1)  # {0, 2, 4, 6, 8}

向集合中添加元素

set1 = {1, 2, 3}
set1.add(4)
set1.add(5)
print(set1)

从集合中删除元素

set1 = {1, 2, 3}
set1.remove(2)
print(set1)

检查成员是否为集合中元素

set1 = {1, 2, 3, 4, 5}
print(2 in set1)  # True

获取集合长度

set1 = {1, 2, 3, 4, 5}
print(len(set1))  # 5

求集合中元素的最大值、最小值、加和

set1 = {1, 2, 3, 4, 5}
print(max(set1))  # 5
print(min(set1))  # 1
print(sum(set1))  # 15

遍历集合

my_set = {1, 2, 3, 4, 5}
for item in my_set:
    print(item)
函数说明
set.add(x)添加元素
set.update(x)添加元素,x可以为列表、元组、字符串、字典等可迭代对象
set.union(x)添加元素后返回一个新的集合,x可以为列表、元组、字符串、字典等可迭代对象
set.remove(x)从集合中移除x,x不存在则报错
set.discard(x)从集合中移除x,x不存在也不报错
set.pop()随机取出集合中的一个元素,如果集合为空则报错
set.clear()清空集合
set.difference(x1,…)求set1和x1的差集,返回一个新的集合
set.difference_update(x1,…)求set1和x1的差集
set.intersection(x1,…)求set1和x1的交集,返回一个新的集合
set.intersection_update(x1,…)求set1和x1的交集
set1 & set2两集合求交集
set1 1 set2两集合求并集
set1 - set2两集合求差集
set1.isdisjoint(set2)判断两集合是否没有交集
set1.issubset(set2)判断set1是否为set2的子集
set1.issuperset(set2)判断set2是否为set1的子集
set1.symmetric_difference(set2)求两集合中不重复的元素,返回一个新的集合
set1.symmetric_difference_update(set2)求两集合中不重复的元素
set.copy()拷贝集合
len(set)返回集合元素个数
max(set)求集合中元素的最大值
min(set)求集合中元素的最小值
sum(set)求集合中元素的加和

字典

一个无序的键值对集合,键是唯一的,而值可以重复。
字典使用 {} 定义,键(key)和值(value)使用 : 连接,每个键值对之间使用 , 分隔。如{key1 : value1, key2 : value2}
字典没有索引。
字典可以通过键来获取对应的值。
值可以取任何数据类型,但键必须是不可变的,如字符串、数字、元组。
(不可变对象(如字符串、数字):因为它们的值永远不变,所以它们算出来的“指纹(哈希值)”永远不变,随时都能精准找到。
可变对象(如列表、集合):因为你随时可以往列表里 append 东西,它的内容变了,算出来的“指纹”也会跟着变。指纹一变,底层的寻址系统就彻底崩溃了。)

创建字典
可以通过{}或dict()创建字典。

dict1 = {}
dict2 = dict()
dict3 = {"name": "Alice", "age": 18, "gender": "male"}
dict4 = dict(name="Bob", age=20, gender="female")
dict5 = dict([("name", "Tom"), ("age", 22), ("gender", "male")])
print(dict1)
print(dict2)
print(dict3)
print(dict4)
print(dict5)

也可以通过字典推导式创建字典。

squares = {x: x**2 for x in range(4)}
print(squares)  # {0: 0, 1: 1, 2: 4, 3: 9}

访问字典:可通过 [] 访问字典中的元素。key不存在时会报错。

dict1 = {"name": "Alice", "age": 18, "gender": "male"}
print(dict1["name"])  # Alice
print(dict1["age"])  # 18
print(dict1["gender"])  # male
print(dict1["address"])  # 报错

也可以通过get()获取字典中的元素。key不存在时会返回None,也可以指定默认值。

dict1 = {"name": "Alice", "age": 18, "gender": "male"}
print(dict1.get("name"))  # Alice
print(dict1.get("age"))  # 18
print(dict1.get("gender"))  # male
print(dict1.get("address"))  # None
print(dict1.get("address", "earth"))  # ear

向字典中添加元素

dict1 = {"name": "Alice", "age": 18, "gender": "male"}
dict1["address"] = "earth"
print(dict1)

修改字典中元素:通过key修改对应的value。

dict1 = {"name": "Alice", "age": 18, "gender": "male"}
dict1["name"] = "Bob"
print(dict1)

检查成员是否为字典中的key

dict1 = {"name": "Alice", "age": 81, "gender": "male"}
print("name" in dict1)  # 检查key是否存在
print("Alice" in dict1)  # 无法直接检查value是否存在

获取字典长度

dict1 = {"name": "Alice", "age": 81, "gender": "male"}
print(len(dict1))  # 3

遍历字典
my_dict = {‘Name’: ‘Tom’, ‘Age’: 17}

# 遍历出所有k
keys = my_dict.keys()
print(f'keys: {keys}')#keys: dict_keys(['Name', 'Age'])
for k in keys:
    print (k)#Name Age
print("-" *20)
# 遍历出所有v
vals = my_dict.values()
print(f'vals: {vals}')#vals: dict_values(['Tom', 17])
print(vals)#Tom 17
for v in vals:
    print (v)
print("-" *20)
# k-v遍历
keys = my_dict.keys()
for k in keys:
    print (k + "---" + str(my_dict[k]))
print("-" *20)
kv = my_dict.items()
print(kv)#dict_items([('Name', 'Tom'), ('Age', 17)])
for i in kv:
    print(i)

删除字典元素

my_dict = {'Name': 'Tom', 'Age': 17}
del my_dict['Name'] # 删除键 'Name'
# my_dict.clear()     # 清空字典
# del my_dict         # 删除字典

print (my_dict)

常用函数

函数说明
del dict[key]根据key删除键值对
dict.pop(key[,default])获取key所对应的value,同时删除该键值对,可设置默认值
dict.popitem()取出字典中的最后插入的键值对,字典为空则报错
dict.clear()清空字典
dict1.update(dict2)将dict2中的键值对更新到dict1中
dict.get(key[,default])获取字典中key对应value,可设置默认值
dict.setdefault(key[,default])获取字典中key对应value,可设置默认值。若key不存在于字典中,将会添加key并将value设为默认值
dict.keys()获取字典所有的key,返回一个视图对象。字典改变,视图也会跟着变化
dict.values()获取字典所有的value,返回一个视图对象
dict.items()获取字典所有的(key,value),返回一个视图对象
dict.copy()拷贝字典
dict.fromkeys(seq[,default])以序列seq中元素做字典的key创建一个新字典,可设置value的默认值

总结

1. 核心对比表格

特性列表(list)元组(tuple)集合(set)字典(dict)
定义符号[](){}{key: value}
是否有序✅ 有序✅ 有序❌ 无序❌ 无序(Python 3.7+ 保持插入顺序)
是否可变✅ 可变❌ 不可变(元素地址不可变)✅ 可变✅ 可变
元素是否唯一❌ 可重复❌ 可重复✅ 必须唯一键唯一,值可重复
是否支持索引✅ 支持✅ 支持❌ 不支持❌ 不支持(通过键访问)
元素类型要求任意类型任意类型必须可哈希(不可变)键必须可哈希,值任意
常用场景动态数据、需要修改固定数据、函数返回多值去重、集合运算键值对映射

2. 定义方式对比

# 列表 - 方括号 []
list1 = [1, 2, 3, 2, 1]
list2 = list([1, 2, 3])
list3 = list("abc")  # ['a', 'b', 'c']

# 元组 - 圆括号 ()
tuple1 = (1, 2, 3, 2, 1)
tuple2 = tuple([1, 2, 3])
tuple3 = 1, 2, 3  # 可以省略括号
tuple4 = (1,)  # 单元素元组必须有逗号

# 集合 - 花括号 {} 或 set()
set1 = {1, 2, 3}
set2 = set([1, 2, 3, 2, 1])  # {1, 2, 3} 自动去重
# set3 = {}  # ❌ 这是空字典,不是空集合
set3 = set()  # ✅ 空集合

# 字典 - 花括号 {} + 键值对
dict1 = {'name': 'Tom', 'age': 17}
dict2 = dict(name='Tom', age=17)
dict3 = dict([('name', 'Tom'), ('age', 17)])

3. 有序性对比

# 列表 - 有序
list1 = [3, 1, 2]
print(list1)      # [3, 1, 2]
print(list1[0])   # 3 - 可以通过索引访问

# 元组 - 有序
tuple1 = (3, 1, 2)
print(tuple1)     # (3, 1, 2)
print(tuple1[0])  # 3 - 可以通过索引访问

# 集合 - 无序
set1 = {3, 1, 2}
print(set1)       # {1, 2, 3} - 顺序可能不同
# print(set1[0])  # ❌ TypeError - 不支持索引

# 字典 - Python 3.7+ 保持插入顺序
dict1 = {'c': 3, 'a': 1, 'b': 2}
print(dict1)      # {'c': 3, 'a': 1, 'b': 2} - 保持顺序
# print(dict1[0]) # ❌ KeyError - 不支持索引
print(dict1['c']) # 3 - 通过键访问

4. 可变性对比

# 列表 - 可变
list1 = [1, 2, 3]
list1[0] = 99      # ✅ 可以修改
list1.append(4)    # ✅ 可以添加
print(list1)       # [99, 2, 3, 4]

# 元组 - 不可变
tuple1 = (1, 2, 3)
# tuple1[0] = 99   # ❌ TypeError
# tuple1.append(4) # ❌ AttributeError
print(tuple1)      # (1, 2, 3)

# 集合 - 可变
set1 = {1, 2, 3}
set1.add(4)        # ✅ 可以添加
set1.remove(1)     # ✅ 可以删除
print(set1)        # {2, 3, 4}

# 字典 - 可变
dict1 = {'a': 1, 'b': 2}
dict1['a'] = 99    # ✅ 可以修改值
dict1['c'] = 3     # ✅ 可以添加键值对
print(dict1)       # {'a': 99, 'b': 2, 'c': 3}

5. 元素唯一性对比

# 列表 - 允许重复
list1 = [1, 2, 2, 3, 3, 3]
print(list1)  # [1, 2, 2, 3, 3, 3]

# 元组 - 允许重复
tuple1 = (1, 2, 2, 3, 3, 3)
print(tuple1)  # (1, 2, 2, 3, 3, 3)

# 集合 - 自动去重
set1 = {1, 2, 2, 3, 3, 3}
print(set1)  # {1, 2, 3}

# 字典 - 键唯一,值可重复
dict1 = {'a': 1, 'b': 2, 'a': 3}  # 键 'a' 重复
print(dict1)  # {'a': 3, 'b': 2} - 后面的覆盖前面的

dict2 = {'a': 1, 'b': 1, 'c': 1}  # 值可以重复
print(dict2)  # {'a': 1, 'b': 1, 'c': 1}

6. 索引和访问方式对比

# 列表 - 通过索引访问
list1 = ['a', 'b', 'c']
print(list1[0])   # 'a'
print(list1[-1])  # 'c'
print(list1[0:2]) # ['a', 'b'] - 支持切片

# 元组 - 通过索引访问
tuple1 = ('a', 'b', 'c')
print(tuple1[0])   # 'a'
print(tuple1[-1])  # 'c'
print(tuple1[0:2]) # ('a', 'b') - 支持切片

# 集合 - 不支持索引
set1 = {'a', 'b', 'c'}
# print(set1[0])   # ❌ TypeError
# 只能遍历
for item in set1:
    print(item)

# 字典 - 通过键访问
dict1 = {'name': 'Tom', 'age': 17}
print(dict1['name'])  # 'Tom'
print(dict1.get('age'))  # 17
# print(dict1[0])  # ❌ KeyError

7. 元素类型要求对比

# 列表 - 任意类型
list1 = [1, 'a', [2, 3], {'x': 4}]  # ✅ 可以混合类型
print(list1)

# 元组 - 任意类型
tuple1 = (1, 'a', [2, 3], {'x': 4})  # ✅ 可以混合类型
print(tuple1)

# 集合 - 元素必须可哈希(不可变)
set1 = {1, 'a', (2, 3)}  # ✅ 数字、字符串、元组可以
print(set1)
# set2 = {1, [2, 3]}  # ❌ TypeError - 列表不可哈希
# set3 = {1, {'x': 4}}  # ❌ TypeError - 字典不可哈希

# 字典 - 键必须可哈希,值任意
dict1 = {1: 'a', 'x': [1, 2], (1, 2): {'y': 3}}  # ✅
print(dict1)
# dict2 = {[1, 2]: 'a'}  # ❌ TypeError - 列表不能做键

8. 常用操作对比

添加元素

# 列表
list1 = [1, 2, 3]
list1.append(4)      # 末尾添加
list1.insert(0, 0)   # 指定位置插入
list1.extend([5, 6]) # 批量添加
print(list1)  # [0, 1, 2, 3, 4, 5, 6]

# 元组 - 不可修改
# tuple1.append(4)  # ❌ AttributeError

# 集合
set1 = {1, 2, 3}
set1.add(4)          # 添加单个元素
set1.update([5, 6])  # 批量添加
print(set1)  # {1, 2, 3, 4, 5, 6}

# 字典
dict1 = {'a': 1}
dict1['b'] = 2       # 添加键值对
dict1.update({'c': 3, 'd': 4})  # 批量添加
print(dict1)  # {'a': 1, 'b': 2, 'c': 3, 'd': 4}

删除元素

# 列表
list1 = [1, 2, 3, 4]
list1.remove(2)    # 删除指定值
del list1[0]       # 删除指定索引
x = list1.pop()    # 删除并返回末尾元素
print(list1)       # [3]

# 元组 - 不可修改
# 只能删除整个元组
# del tuple1

# 集合
set1 = {1, 2, 3, 4}
set1.remove(2)     # 删除指定值(不存在会报错)
set1.discard(5)    # 删除指定值(不存在不报错)
print(set1)        # {1, 3, 4}

# 字典
dict1 = {'a': 1, 'b': 2, 'c': 3}
del dict1['a']     # 删除指定键
x = dict1.pop('b') # 删除并返回值
print(dict1)       # {'c': 3}

9. 遍历方式对比

# 列表
list1 = [1, 2, 3]
for item in list1:
    print(item)
for i, item in enumerate(list1):  # 带索引
    print(i, item)

# 元组
tuple1 = (1, 2, 3)
for item in tuple1:
    print(item)

# 集合
set1 = {1, 2, 3}
for item in set1:
    print(item)

# 字典
dict1 = {'a': 1, 'b': 2}
for key in dict1:              # 遍历键
    print(key)
for value in dict1.values():   # 遍历值
    print(value)
for k, v in dict1.items():     # 遍历键值对
    print(k, v)

10. 特有操作对比

列表特有

list1 = [3, 1, 4, 1, 5]
list1.sort()         # 原地排序
print(list1)         # [1, 1, 3, 4, 5]
list1.reverse()      # 反转
print(list1)         # [5, 4, 3, 1, 1]
print(list1.count(1))  # 2 - 统计某值出现次数
print(list1.index(4))  # 2 - 查找某值的索引

集合特有(集合运算)

set1 = {1, 2, 3, 4}
set2 = {3, 4, 5, 6}

print(set1 & set2)   # {3, 4} - 交集
print(set1 | set2)   # {1, 2, 3, 4, 5, 6} - 并集
print(set1 - set2)   # {1, 2} - 差集
print(set1 ^ set2)   # {1, 2, 5, 6} - 对称差集

字典特有

dict1 = {'a': 1, 'b': 2, 'c': 3}

print(dict1.keys())    # dict_keys(['a', 'b', 'c'])
print(dict1.values())  # dict_values([1, 2, 3])
print(dict1.items())   # dict_items([('a', 1), ('b', 2), ('c', 3)])

print(dict1.get('a'))       # 1 - 安全获取值
print(dict1.get('x', 0))    # 0 - 不存在返回默认值

dict1.setdefault('d', 4)    # 键不存在时设置默认值
print(dict1)  # {'a': 1, 'b': 2, 'c': 3, 'd': 4}

11. 性能对比

操作列表元组集合字典
查找元素O(n)O(n)O(1)O(1)
插入元素O(1)~O(n)O(1)O(1)
删除元素O(n)O(1)O(1)
内存占用中等最小较大最大

12. 使用场景建议

列表

# ✅ 适合:
# - 需要保持顺序
# - 需要频繁修改
# - 允许重复元素

students = ['Tom', 'Jerry', 'Alice']
scores = [85, 92, 78]

元组

# ✅ 适合:
# - 数据不会改变
# - 函数返回多个值
# - 作为字典的键

point = (10, 20)  # 坐标
rgb = (255, 128, 0)  # 颜色

def get_user():
    return ('Tom', 17)  # 返回多个值

集合

# ✅ 适合:
# - 去重
# - 集合运算(交集、并集等)
# - 快速查找

# 去重
numbers = [1, 2, 2, 3, 3, 3]
unique = list(set(numbers))  # [1, 2, 3]

# 快速查找
allowed_users = {'Tom', 'Jerry', 'Alice'}
if 'Tom' in allowed_users:  # O(1) 时间
    print("允许访问")

字典

# ✅ 适合:
# - 键值对映射
# - 配置信息
# - 快速查找

# 用户信息
user = {
    'name': 'Tom',
    'age': 17,
    'email': 'tom@example.com'
}

# 计数
words = ['apple', 'banana', 'apple']
count = {}
for word in words:
    count[word] = count.get(word, 0) + 1
print(count)  # {'apple': 2, 'banana': 1}

13. 类型转换

# 互相转换
list1 = [1, 2, 3, 2, 1]

# 转元组
tuple1 = tuple(list1)
print(tuple1)  # (1, 2, 3, 2, 1)

# 转集合(自动去重)
set1 = set(list1)
print(set1)  # {1, 2, 3}

# 集合转列表
list2 = list(set1)
print(list2)  # [1, 2, 3]

# 字典相关
dict1 = {'a': 1, 'b': 2}
print(list(dict1))        # ['a', 'b'] - 键的列表
print(list(dict1.values()))  # [1, 2] - 值的列表
print(list(dict1.items()))   # [('a', 1), ('b', 2)] - 键值对列表

14. 记忆口诀

列表方括号,有序可改能重复
元组圆括号,有序不变能重复
集合花括号,无序可改必唯一
字典键值对,无序可改键唯一

15. 快速选择指南

需要修改数据?
  ├─ 是 → 列表/集合/字典
  └─ 否 → 元组

需要保持顺序?
  ├─ 是 → 列表/元组
  └─ 否 → 集合/字典

需要去重?
  ├─ 是 → 集合
  └─ 否 → 列表/元组

需要键值对映射?
  ├─ 是 → 字典
  └─ 否 → 列表/元组/集合

希望这个对比能帮助你理解这四种数据类型的区别!如果有任何疑问,随时问我。

更多推荐