02 Python数据容器

1 列表(list)

1.1 列表的创建与访问

列表类似C++的数组,不过列表中的数据可以为不同的数据类型,并且可以嵌套,嵌套时类似C++的多维数组。
列表定义用[]包围,以,分割,正向下标从0开始,有反向索引,从-1开始,从后往前,依次递减。

ls = []   # 空列表

demo_list = [11, '哈哈', 3.14, [1, -2]]
# 正向索引    0      1     2       3 
# 反向索引   -4     -3    -2      -1

demo[1]  # 得到 '哈哈'
demo[-1][0]  # 得到 1

列表可以使用+拼接或使用*实现重复计算。

ls1 = [1, 2] * 2
ls2 = [3, 4]

print(ls1)  # [1, 2, 1, 2]
print(ls1 + ls2)  # [1, 2, 1, 2, 3, 4]

1.2 列表生成式

列表生成式的效率很高,强烈建议使用列表生成式来创建列表

要生成的元素 循环 过滤条件

# 将表达式按照特定条件依次放到列表中,生成了1~10
ls = [i + 1 for i in range(10)]  

# 等价于以下循环
for i in range(10):
	ls.append(i + 1)
	
# 有条件的列表推导式
ls = [i for i in range(100) if i % 2 == 0]  # 生成0~99的偶数列表

# 多重循环的列表推导式
ls = [(x, y) for x in range(3) for y in range(2)] # 生成x,y坐标

推导式可以用来生成列表、集合、字典。

dic1 = {'zhangsan': 18, 'lisi': 22, 'wangwu': 15, 'zhaoliu': 16}  

# 生成字典
dic2 = {k: v for k, v in dic1.items() if v >= 18}  # 过滤大于18岁的人

# 生成集合
st1 = {k for k in dic1.keys() if dic1[k] >= 18}  

1.3 列表的遍历

# while方式
i = 0
while i < len(my_list):
	print(my_list[i])
	i++

# for方式
for i in my_list:
	print(i)

1.4 常用方法

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

2 元组(tuple)

2.1 元组的创建与访问

元组与列表类似,不同之处在于元组的元素不能修改,元组使用(),列表使用[]

tp = ()    # 空元组

nums = (1, 4, 6)

# 元组内只有一个元素时,需要有逗号在内,否则小括号会识别为运算符
nums = (1,)  √
nums = (1)   ×

# 元组的访问和列表完全一样,通过下标访问,支持反向下标
nums[1]

2.2 元组的“可变”

元组内有list的时候,元组依然遵循元素不可变,但list内的元素可以修改。这是因为元组存储的时候本质上存的是list的地址,只要地址不变,元组元素就没有修改,而所指内容是否变化和元组无关。正因为如此,替换为别的list也是不被允许的,因为地址发生了改变。

nums = (1, 2, [1, 2, 3])
nums = (1, 2, 地址)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

2.3 打包和解包

当我们把多个用逗号分隔的值赋给一个变量时,多个值会打包成一个元组类型;当我们把一个元组赋值给多个变量时,元组会解包成多个值然后分别赋给对应的变量。

# 打包操作
a = 1, 10, 100
print(type(a))  # <class 'tuple'>

# 解包操作
i, j, k = a
print(i, j, k)  # 1 10 100

解包操作对所有序列的成立,包括列表、元组、字符串、range都可以使用解包操作。

解包时元素个数和变量个数不匹配会引发ValueError异常,不过我们可以使用星号表达式解决变量少于元素个数的情况,让一个变量接收多个值。

  1. 星号修饰的变量会变成一个列表,可以存放0个或多个元素
  2. 解包语法中,只能有一个型号表达式
ls = [1, 2, 3, 4, 5, 6]  

# 可以改变型号表达式的位置,会自动匹配
i, j, *k = ls  
print(i, j, k)  # 1 2 [3, 4, 5, 6]
  
*i, j, k = ls  
print(i, j, k)  # [1, 2, 3, 4] 5 6

a, b = b, aa, b, c = b, c, a实际并没有用到打包解包语法,而是有特定的字节码指令实现这两个操作,效率非常高,在三个以上的变量交换时需要使用打包解包。

2.4 常用方法

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

3 字符串(str)

3.1 字符串的创建和访问

字符串同列表、元组一样,可以通过下标和反向下标进行访问。不过和C++非常不同的一点是,字符串是无法修改的容器。也就是说如果要完成修改操作,只能得到一个新的字符串,旧的字符串是无法修改的。

# 字符串可以使用单引号、双引号、三引号进行定义,使用三引号时可以跨行。

s = ""   # 空字符串

s = 'hhh'
s = "hhh"
s = """hhh
hhhh
hh
"""

# 单引号里面可以包双引号,双引号里面可以包单引号
s = "人工'智'能"
s = '人工"智"能'

print(s[1])
  • 字符串内部使用\进行转义,比如\n换行、\t缩进,又或者转义\ ' "这些特殊字符
  • Python中以rR开头的字符串叫做原始字符串,字符串内都是本来的含义,没有所谓转义字符
# 很多字符需要转义需要很多\,可以使用r''或R''表示内部字符串默认不转义
print('\\\t\\')  # \	\
print(r'\\\t\\') # \\\t\\

3.2 字符串的运算

  • 字符串比较时按照字典序从前往后,只要其中一位大,后面就不用比较了
  • 可以使用+进行拼接,还可以使用*将字符串重复

3.3 字符串的格式化

两种方法变量的位置都可以填写表达式,Python会先计算再填入。

# 方法一:使用占位符
"名字:%s" % name
"名字:%s 年龄:%d 分数:%.2f" % (name, age, score)

%md %mf   限制m位宽度(小数点也算一位)
%.nf      保留n位小数 
%m.nf     限制m位宽度,并保留n位小数

# 想要打出 %,可以使用%%
print("%.2f%%" % 82.5)
# 方法二:f-string格式化,默认不理会类型,也不做精度控制
f"名字:{name} 年龄:{age} 分数:{score}"

# 这种方式也可以控制精度
f"{变量:m.n f | d}"
f"分数{score:.2f}"

3.4 常用方法

由于字符串不可变,所以使用字符串的方法并不会改变原来的字符串,而是产生新的字符串。

# 转大写
su = s.upper()

# 转小写
sl = s.lower()

# replace用法,生成新的字符串,原字符串不变
s = "Python好玩真好玩"
new_s = s.replace("好玩", "有趣")
print(s)      # 结果还是  Python好玩真好玩
print(new_s)  # 修改后的  Python有趣真有趣

# split用法,原字符串不变,生成一个新列表
name = "Python-Java-C++"
name_list = name.split('-')
print(name)        # Python-Java-C++
print(name_list)   # ['Python', 'Java', 'C++']

# strip用法,去除前后指定字符串
demo = "   hhhh  "
new1 = demo.strip()       # 默认去除前后空格和换行符
demo = "1211哈哈哈21121"
new2 = demo.strip("12")   # 按照单个字符,'1'和'2'都会删除
print(new2)    # 哈哈哈

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

4 序列的切片

序列是指:内容连续、有序,可使用下标索引的一类数据容器。
上述的列表、元组、字符串都是序列。序列支持切片操作,切片就是从原序列中取出一个子序列。

语法:序列[起始下标:结束下标:步长](类似range序列,[起始,结束)范围内指定步长)
表示从序列中,从指定位置开始,依次取出元素,到指定位置结束,得到一个新序列。

  • 起始下标表示从何处开始,可以留空,留空视作从头开始
  • 结束下标(不含)表示何处结束,可以留空,留空视作截取到结尾
  • 步长表示依次取元素的间隔(可以为负,反向走,起始下标也要在结束下标右边)

注意,此操作不会影响序列本身,而是会得到一个新的序列(列表、元组、字符串)

5 字典(dict)

5.1 字典的创建和访问

字典使用{}包围,存储的元素是键值对key:value,并且key不可重复,重复会覆盖原有数据。

  • key 数据类型必须为不可变类型,不可为字典、列表,一般类型用:字符串、整数
  • value 数据类型随意,不限制
d = {}      # 空字典
d = dict()  # 空字典

d = {"zhangsan":100, "lisi":59}

# 集合不可用下标进行访问,但可以使用key来取得对应的value
print(d["zhangsan"])  # 结果为100

字典访问到不存在的key会报错,可以使用in字典.get(键, 返回值)来检验。

# 使用 in 检验
d = {'zhangsan': 18}
if 'zhangsan' in d:  # 相反还有 not in
	print('在字典')

# 使用 字典.get(键, 返回值) 方法
# 键存在则返回值,键不存在默认返回 None,也可以指定返回值
if d.get('lisi') is None:  # d.get('lisi', 1) == 1 作用一样  
    print('不在字典')

# 可以用get()很方便地统计出现次数
s = input()  
counter = {}  
for c in s:  
    if c.isalpha():  
        counter[c] = counter.get(c, 0) + 1  # 存在返回已有值,不存在返回0

字典通过哈希算法计算key的位置,所以字典的查找和插入操作极快。由于要保证hash的正确性,作为key的对象就不能变。在Python中,字符串和整数都不可变,可以放心用作keylist可变不能作为key

5.2 字典的遍历

# 迭代字典的键
for k in d.keys():  # 等同于 for i in d:
	print(f"名字:{k} 分数:{d[k]}")

# 迭代字典的值
for v in d.values():
	print(v)

# 迭代字典的键值对
for k, v in d.items():  
    print(f'{k}: {v}')

5.3 常用方法

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

6 集合(set)

6.1 集合的创建

setdict类似也是一组key的集合,但不存储value,由于key不能重复,所以在set中没有重复的key。集合内部是去重并且无序的,使用{}包围。因为无序,所以集合不可用下标进行访问。

s = set()  # 空集合,s = {} 不是空集合,而是空字典

s = {1, 2, 3} 

setdict底层原理一样,唯一的区别仅仅在于没有存储valuekey是唯一的保证了set内部不会有重复元素,由于无法判断两个可变对象是否相等,所以不能存放可变对象

注意与C++非常不同的是,集合不会自动排序dictset 的底层哈希表会让它看起来好像有顺序,但这不是排序,只是哈希存储的结果,顺序不稳定)

6.2 集合的运算

set之间有很方便的取交集&和取并集|运算。

s1 = {1, 2, 3, 4}
s2 = {1, 2, 5, 6}
print(s1 & s2)  # 交集 {1, 2}
print(s1 | s2)  # 并集 {1, 2, 3, 4, 5, 6}

6.3 集合的遍历

由于集合不支持下标访问,所以不能使用while循环。

for i in s:
	print(i)

6.4 常用操作

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

7 容器对比

列表、元组字符串为序列类型,集合、字典为非序列类型。

  • 是否支持下标索引
    • 支持:列表、元组、字符串
    • 不支持:集合、字典
  • 是否支持重复元素:
    • 支持:列表、元组、字符串
    • 不支持:集合、字典
  • 是否可以修改
    • 支持:列表、集合、字典
    • 不支持:元组、字符串

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

8 容器通用操作

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  • sorted:接收任意可迭代对象(list、tuple、set、dict、str等),返回一个新的列表(不修改原对象)。
  • .sort()list专属方法,直接在原列表上排序,不会返回新列表(返回None)。
tp = (3, 2, 4, 1)
tp_ls = sorted(tp)  # 返回值为列表

ls = [3, 2, 4, 1]
ls.sort()  # 直接对ls本身进行排序

sorted有类似C++中的cmp函数,可以自定义排序规则,并且支持lambda匿名函数,用法如下:

# 默认以第一个元素作为依据进行排序
ls = [('bob', 70), ('alice', 80), ('carl', 100)]
ls = sorted(ls)
print(ls)  # [('alice', 80), ('bob', 70), ('carl', 100)]

# x 是需要排序容器的一个元素,sorted 会把每个元素传入自定义函数
def cmp(x):
	return x[1]
	
# 自定义排序规则
ls = sorted(ls, key=cmp)
print(ls)  # [('bob', 70), ('alice', 80), ('carl', 100)]

# lambda函数+逆序排列
ls = sorted(ls, reverse=True, key=lambda x: x[1])  
print(ls)  # [('carl', 100), ('alice', 80), ('bob', 70)]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

OG one.Z

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值