01-详解 Python 容器的用法

本文详细介绍了Python中的容器类型,包括列表、字典和元组的用法。列表具备异构性、有序性和本地可修改性,支持增删改查等多种操作。字典是一种无序的键值对集合,提供了动态生成和修改的多种方法。元组则被视为不可变的列表,有特殊操作和排序方式。这些基础知识对于Python开发者至关重要。
摘要由CSDN通过智能技术生成

0.本集概览

1.列表用法详解
2.字典用法详解
3.元组用法详解

1.容器类型概述

Python中有一种被称之为“容器”的数据类型,顾名思义,就是专门用来存放其他类型数据的对象。很多人刚刚使用Python的时候,往往最先接触的就是这种容器对象,比如列表、字典、元组等等。它们功能全面,使用也很方便,可以解决很多实际问题。

在这一些容器当中,我们首先来介绍列表:

2.列表用法详解

Python列表用起来非常灵活,它有三大优点,我们一个一个来说,聊完了这三个优点,列表的基本操作我们就掌握了:

2.1.优点之一:列表里想装啥就装啥

即:他可以包含不同种类、任意类型的对象,甚至可以嵌套列表,专业点的词儿叫:异构性,我们看一个例子:
代码片段:

L1 = [1, 2, 3, 4, 5]
L2 = [1, 'spam', [2.3, 4]]
L3 = []

看这三个列表的初始化过程,异构性就搞清楚了,特别是L2列表,它同时包含了好几种不同的数据类型,甚至还嵌套了列表。

2.2.优点之二:列表里装的元素都是有顺序的

即:可以按照位置序号获取单个元素,也可以用分片的方法来进行多个连续元素的获取,来个专业词汇,叫做:有序性

按位置序号索引,例如L1[2]这种方式来访问列表中的元素只是最简单的一种,我来重点来说说分片操作这个独特用法,先看看这个例子:
代码片段:

L = [1,2,3,4,5,6,7,8]
print(L[1:3])

运行结果:

[2, 3]

我们从列表L中从左往右截取了一个片段。关于截取片段左右边界与索引值的对应关系,我们只需记住这么一个口诀**“左闭右开”**就OK了:

分片索引中第一个参数1表示左侧开始的索引1(从0开始计数),因此起始的元素就是整形数2,第二个参数3表示在右侧终止的索引值为3,即整形数4,但要记住他是不包含在截取的序列中的。

分片还有几种常见用法:

如果省略掉终止索引,就表示一直截取到末尾:
代码片段:

L = [1,2,3,4,5,6,7,8]
print(L[1:])

运行结果:

[2, 3, 4, 5, 6, 7, 8]

同理,如果省略掉起始索引,就表示从起始元素就开始截取:
代码片段:

L = [1,2,3,4,5,6,7,8]
print(L[:4])

运行结果:

[1, 2, 3, 4]

还可以用负索引,目前我们使用的都是正索引,即从左往右的索引值,最左侧的索引值为0,往右依次加1;还有一种负索引的表示法,即从右往左数,最右侧是-1,往左依次减1,即-2,-3以此类推:
代码片段:

L = [1,2,3,4,5,6,7,8]
print(L[3:-1])

运行结果:

[4, 5, 6, 7]

如果想跳着截取,那就用上第三个参数,步进值参数,这个默认是1,即1个挨着1个的取,如果我们想跳着截取,那就得专门设置这个步进参数了。
代码片段:

L = [1,2,3,4,5,6,7,8]
print(L[0::2])

运行结果:

[1, 3, 5, 7]

这里我问大家一个问题:**如果我对截取出的分片进行修改,会影响到原始的列表吗?**我们眼见为实做个试验:
代码片段:

L = [1,2,3,4,5,6,7,8]
b = L[3:-1]
print('before change:b={}'.format(b))
b[0]=111
print('after change:b={}'.format(b))
print('after change:L={}'.format(L))

运行结果:

before change:b=[4, 5, 6, 7]
after change:b=[111, 5, 6, 7]
after change:L=[1, 2, 3, 4, 5, 6, 7, 8]

很明显,对原始列表L进行分片切割后,产生了一个全新的列表。用变量b获取了L的分片后,实质是获取了L分片的一个新的独立拷贝。因此,你在列表b上做修改,是影响不了L的。

2.3.优点之三:列表元素本地可修改

列表的大小和内容可以随意改变,在插入、删除、修改列表元素时,不需要建立一份新的列表拷贝,而是在原来的内存地址上直接修改列表对象。这个叫**“本地可修改”**。

2.3.1.增加新元素的使用场景

首先看增加新元素的三个使用场景:
代码片段:

L = [1,2,3,4]
L.append(5)
print(L)

运行结果:

[1, 2, 3, 4, 5]

代码片段:

L = [1,2,3,4]
L.insert(1,10)
print(L)

运行结果:

[1, 10, 2, 3, 4]

代码片段:

L = [1,2,3,4]
L.extend([11,22,33])
print(L)

运行结果:

[1, 2, 3, 4, 11, 22, 33]

这三个用法有些不同,append方法只能在尾部加入insert方法可在任意位置加入,比如上面例子,我们在列表的索引位置为1的地方加入元素10,如果指定的索引值大于序列的总长度,则自动加到末尾;extend方法则可以在尾部一次性加入多个元素。我们来看一个练习代码:
代码片段:

L = [1,2,3,4,5]
L = L.insert(6,2)
print(L[2])

运行结果:

Traceback (most recent call last):
 File "E:/12homework/12homework.py", line 3, in <module>
print(L[2])
TypeError: 'NoneType' object is not subscriptable

这里犯了一个常见的错误,因为我们说过插入是就地修改,而不是返回修改后的新列表。insert方法的返回值是None,这么干换句话说,会彻底失去之前列表的引用,因为你把None值赋给了L,你就无法找到之前的列表了。append和extend方法也是这样

2.3.2.删除的几种使用场景

最简单直接的,用remove方法,传入指定要删除的对象,注意:它也是在原列表上就地删除,返回值为None
代码片段:

L1 = ['aa','bb','cc']
L1.remove('aa')
print(L1)

运行结果:

['bb', 'cc']

这里注意,还有一个内置方法del,它额外的功能是可以删除列表中的一个分片。
代码片段:

del L1[1:3]

还有一个pop方法,它在末端删除一个元素,并可以将删除的元素作为返回值返回给调用者。
代码片段:

L1 = [1,2,3]
print(L1.pop())#末端删除一个元素,弹出删除的值
print(L1)

运行结果:

3
[1, 2]

2.3.3.元素修改的几种场景

元素修改最简单的,就是像下面这种直接用索引做元素修改的情况
代码片段:

L = [4,5,6,7,8,9]
L[0] = 0

当然元素修改,还有更有意思的用法,主要就说分片赋值本地排序这两个问题:
代码片段:

L = [4,5,6,7,8,9]
L[1:3] = ['aa','bb','cc','dd']
print(L)

运行结果:

[4, 'aa', 'bb', 'cc', 'dd', 7, 8, 9]

分片赋值的本质是先在原列表上删除指定分片,然后在删除的位置插入新的列表,因此左右两边的长度可以不等。

本地排序非常方便,看看下面的例子就明白了。注意排序也是在本地修改,而不是将排好序的列表作为返回值返回。
代码片段:

L = [1,5,3,8,3,2,10]
L.sort()
print(L)
L.reverse()
print(L)

运行结果:

[1, 2, 3, 3, 5, 8, 10]
[10, 8, 5, 3, 3, 2, 1]

列表的相关内容就介绍这么多,下面说说字典:

3.字典用法详解

字典这个容器类型真的非常好用,也非常重要。

字典和列表完全不同,**字典里的对象是无序的,他是通过一对对的键和值来反映一种映射关系。**字典里,每个键都是唯一的,我们可以通过键来存取对应的值,而不能像列表那样通过位置来索引。

3.1.简单的生成、读取和修改操作

首先来看看怎样用最简单的方法生成一个字典,先弄一个出来再说。
代码片段:

D = {
'name':{'first':'Bob', 'last':'Smith'},
'job' : ['dev','mgr'],
'age' : 0.5,
'addr': 'BeiJing'
}
print(D)

运行结果:

{'job': ['dev', 'mgr'], 'addr': 'BeiJing', 'name': {'first': 'Bob', 'last': 'Smith'}, 'age': 0.5}

从这个例子的输出结果我们可以看出,字典也是可以包含任意的数据类型,即所谓的异构性,甚至可以嵌套一个字典,同时从打印的结果看,字典里的各个元素确实没有什么顺序可言

对字典值的读取和修改也很简单
代码片段:

D = {'food':'spam', 'quality':4, 'color': 'pink'}
print(D['food'])
D['sex'] = 'gender'
print(D)

运行结果:

spam
{'food': 'spam', 'color': 'pink', 'quality': 4, 'sex': 'gender'}

我们用‘food’键就可以读取其对应的值—字符串对象‘spam’,此外我们还可以原地增加‘sex’键以及对应的值,当然,也可以原地修改其他已有的键和值。

但是,我们不难发现:这种方法很死板。他要求我们一个一个的把数据手动输入来构建字典,这样子感觉不是很方便。特别是当我们事先不知道字典有哪些键和值的时候,如果想利用在程序中动态获取的数据集来生成字典,上述方法就办不到了

3.2.几种灵活的字典生成方法

基于这种需求,我们再介绍其他几个生成字典的方法:

3.2.1 初始为空字典,动态填充新的键和值

代码片段:

D = {}
D['name'] = 'Bob'
D['job'] = 'dev'
print(D)

运行结果:

{'name': 'Bob', 'job': 'dev'}

3.2.2.用列表动态生成字典

一般来说字典的键是事先约定好的,比如姓名、性别、生日等等,而值往往是要在程序运行过程当中通过用户输入、网页数据抓取等不同手段动态获取的。本方法可以在获取值列表后动态生成一个字典。
代码片段:

key_list = ['a','b','c']
value_list = [11,22,33]
D = dict(zip(key_list, value_list))
print(D)

运行结果:

{'a': 11, 'c': 33, 'b': 22}

3.3.3.用键值对元组组成的列表构造字典

元组我们后面要讲,就是这个圆括号
代码片段:

D = dict([('aa',11),('bb',22),('cc',33)])
print(D)

运行结果:

{'cc': 33, 'aa': 11, 'bb': 22}

3.3.4.利用已有字典合并生成新字典

做法很简单:
代码片段:

D1 = {'a':1,'b':2, 'c':3}
D2 = {'c':8, 'd':9}
D1.update(D2)
print(D1)

运行结果:

{'c': 8, 'b': 2, 'a': 1, 'd': 9}

不过要注意,如果这两个字典中有冲突的键,那么会无规律的进行覆盖,所以应该避免这种情况

3.3.字典键不存在时的处理技巧

我们想想,如果访问一个不存在的字典键,程序应该会报错吧。这么说也对,也不对。我们具体看看对于键不存在这种情况下的处理技巧。
代码片段:

D = {'a':1,'b':2, 'c':3}
print(D['d'])

运行结果:

Traceback (most recent call last):
 File "E:/12homework/12homework.py", line 2, in <module>
print(D['d'])
KeyError: 'd'

用这种直接访问的方式,如果键不存在就会报错,但是可以引入in判断方法进行避免
代码片段:

D = {'a':1, 'b':2}
print('c' in D)
if not 'c' in D:
print('missing')

运行结果:

False
Missing

其实,有一种更高级的方法实现了上述的判断功能,那就是get方法。get方法中第二个参数指的是键不存在时指定返回的默认值,如果不设置这个值,则返回None
代码片段:

D = {'a':11,'b':22, 'c':33}
print(D.get('d',0))

运行结果:

0

3.4.一次性高效获取键值列表的方法

我们在实际使用字典时,很多情况下不应该这么一个一个的手动访问字典键,可以用下面的方法来一次性获取包含所有键的列表:
代码片段:

D = {'a': 11, 'b': 22, 'c': 33, 'd': 44, 'e': 55}
print(list(D.keys()))

运行结果:

['b', 'a', 'd', 'e', 'c']

D.Keys方法返回的是一个迭代器,而不是直接就给出一个列表,关于迭代器后面会专门讲的,这里只需记住此处将迭代器作为参数来初始化一个list,可以一次性生成所有的键,并将其打印出来。

想获取值的列表,处理方法也十分类似
代码片段:

D = {'a': 11, 'b': 22, 'c': 33, 'd': 44, 'e': 55}
print(list(D.values()))

运行结果:

[11, 33, 44, 55, 22]

我们还可以用同样类似的方法同时获取键值对的列表
代码片段:

D = {'a': 11, 'b': 22, 'c': 33, 'd': 44, 'e': 55}
print(list(D.items()))

运行结果:

[('d', 44), ('a', 11), ('c', 33), ('e', 55), ('b', 22)]

3.5.字典的删除与排序

这方面字典和列表大同小异,而且删除也是利用del和pop两种方法
代码片段:

D = {'a': 11, 'b': 22, 'c': 33, 'd': 44, 'e': 55}
del D['a']
print(D)

运行结果:

{'b': 22, 'c': 33, 'e': 55, 'd': 44}

pop方法是在删除指定键对应的元素的同时,返回这个键所对应的值
代码片段:

D = {'a': 11, 'b': 22, 'c': 33, 'd': 44, 'e': 55}
print(D.pop('a'))
print(D)

运行结果:

11
{'b': 22, 'e': 55, 'd': 44, 'c': 33}

在这一节的最开始我们说过,字典里对象是无序的,那怎么还存在排序的概念呢?实际上,字典的排序操作实际上是在对键进行排序,他返回一个排好序的键的列表
代码片段:

D = {'a': 11, 'b': 22, 'c': 33, 'd': 44, 'e': 55}
print(sorted(D))
print(sorted(D.keys()))

运行结果:

['a', 'b', 'c', 'd', 'e']
['a', 'b', 'c', 'd', 'e']

这里埋一个伏笔,内置函数sorted接受的都是可迭代对象,这个反复出现的概念后面我们一定会好好谈谈。

4.元组用法详解

最后一节说说元组,元组很简单,核心就是一句话:可以看作是不可变的列表。

4.1.元组看作是不可变列表

代码片段:

T = (1,2,3,4)
M = ('spam', 3.0, [11,22,33])
print(T[1])
print(M[2][0])

运行结果:

2
11

4.2.元组的一些特殊操作

元组有一种特殊的方法,可以一次性获取元组中的所有项
代码片段:

a,b = (1,2)
print('a={},b={}'.format(a,b))

运行结果:

a=1,b=2

他也可以和其他元组进行连接操作
代码片段:

T1 = (1,2,3,4)
T2 = (5,6,7,8)
print(T1 + T2)

运行结果:

(1, 2, 3, 4, 5, 6, 7, 8)

基于位置偏移的操作如索引和分片,元组和列表的用法完全一样。他和列表的关键区别在于他的不可变性,这有利于保持数据的完整性。

4.3.元组的排序

至于说元组的排序,由于其不可变性,所以就地排序肯定是不行的。元组排序的一种方法是先将其转化为列表,本地排序后再转化回元组。
代码片段:

T = ('cc','bb','dd','aa')
tmp = list(T)
tmp.sort()
T = tuple(tmp)
print(T)

运行结果:

('aa', 'bb', 'cc', 'dd')

或者用内置sorted方法,传入一个元组,返回一个已经排好序的list序列
代码片段:

T = ('cc','bb','dd','aa')
print(sorted(T))

运行结果:

['aa', 'bb', 'cc', 'dd']

元组不难,主要内容就讲这么多了。

5.小结

这一节,我们主要学习了三种核心容器数据类型:列表、字典、元组,详细解析了他们的关键用法,很多实用技巧有助于我们高效的进行数据处理。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

石 溪

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

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

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

打赏作者

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

抵扣说明:

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

余额充值