容器类数据类型python内置数据类型中,有一类数据类型,它能像容器那样存储不同的元素。列表list、元组tuple、字符串str、字典dict、集合set都是属于容器类型。
一、容器类对象的几种类别
容器:container 序列:sequence 映射:mapping
序列(sequence)是一种数据结构,是有序的容器类型,list、str和tuple都属于序列,其中列表是可变的(你可以修改其内容),而元组和字符串是不可变的(一旦创建,内容就是固定的)。
熟悉Python中的内存机制,这种不可变是指类型内的元素是不能进行修改的
注:像下面介绍的字符串的切割,链接等操作,看起来修改了字符串,实质上并没有修改原来的字符串,在内存中字符串还是原来的字符串。操作在内存中产生了新的字符串
序列索引值:序列的每个元素都有索引值,用索引值我们能访问到指定元素,
相比于C语言中的数组是基于0的下标索引,即长度为n的数组,第一个值的下标为0,最后一个元素的下标为n-1 。
Python中序列索引值有更灵活的“定义”,不但有顺序索引:0~(n-1),还有倒序索引:-1~ -n ,-n是第一个元素,-1是最后一个元素。
看起来我们可把序列索引值以理解为:相对于第一个元素的偏移量。这样的倒序索引和正序索引看起来就比较自然了。
序列的特有操作:切片、链接+和重复*
-
切片 : 切片适合有序的容器类型(序列)。
语法:s = [start:end:step]
# start:开始位置, end:结束位置;start和end指定了切片的范围.
# step: 步进值,从开始位置到结束位置的步进值,。step可指定为正数(步进方向可认为是顺序)或负数(步进方向可认 为是逆序)。默认步进值为1 因此可省略最后一个冒号和step : s[start:end]
# 报错的情况: 按照步进的方向,开始到结束的区间不能越过边界,不符合切片范围的会返回对应的空序列 [ ] () ‘ ‘
# start和end可以不指定,默认是步进方向的首尾位置。
>>> lt = [0, 1, 2, 3, 4, 5]
>>> lt[::2]
[0, 2, 4]
>>> lt[::-2]
[5, 3, 1]
# 指定start和end的时候,切片范围遵循左开右闭原则:切片范围不包含end。 开始值和结束值都是遵循序列索引值的。
注意:在不指定开始位置和结束位置的时候,结束位置是被包含在切片范围内的。
>>> lt = [0, 1, 2, 3, 4, 5, 6]
>>> lt[::2]
[0, 2, 4, 6]
# 切片操作是为了访问序列的一部分。 灵活的使用序列的索引值和步进值来解决需求。
# 0.查找序列的后三个元素
>>> s = 'helloworld'
>>> s[-3:]
'rld'
# 1.序列元素逆序
>>> s = 'hello,world!'
>>> s[::-1]
'!dlrow,olleh'
# 切片赋值:另外对于列表,可以使用赋值语句给切片赋值
注意:赋值语句的右边必须是可迭代对象(iterable),如果是字典的话,会将其键赋值到切片位置
>>> lt = [0, 1, 2, 3, 4, 5]
>>> lt[0:2]=[99]
>>> lt
[99, 2, 3, 4, 5]
>>> lt[0:2] = {'name': 'marsen'}
>>> lt
['name', 3, 4, 5]
-
链接+和重复*:
序列支持 + 和 * 操作的,本质上是生成了新的序列,原来的序列保持不变
# 链接操作 + 是对序列元素的拼接
>>> s = 'hello'
>>> s + ',' + 'world!'
'hello,world!'
>>> lt = [0, 1, 2]
>>> lt + [3, 4] + [5]
[0, 1, 2, 3, 4, 5]
>>> tp = (0, 1, 2)
>>> tp + (3, 4) + (5,)
(0, 1, 2, 3, 4, 5)
# 重复操作 * 是序列元素的重复
>>> tp = (0, 1)
>>> tp * 3
(0, 1, 0, 1, 0, 1)
>>> tp
(0, 1)
>>> lt = [0, 1]
>>> lt * 3
[0, 1, 0, 1, 0, 1]
>>> lt
[0, 1]
>>> s = 'hi'
>>> s * 3
'hihihi'
>>> s
'hi'
映射(mapping),通过名称访问其各个值的数据结构,称之为mapping, 字典(dict)是Python中唯一的内置映射类型。
其他容器类型:集合(set)
二、容器类对象通用操作
容器类变量有一些共同点:
-
取值(访问):container [ 索引 ]
-
遍历: 使用for in进行元素遍历
-
成员判断: 使用成员运算符 in 来检查元素是否存在
-
计算长度:len(container): 使用系统函数len( )返回容器内项的数量,对于字典来说,返回的就是键值对的个数
-
比较: max() /min() 以及 同类型对象之间 > < 的比较
0,取值(访问):container [ 索引 ]
变量后跟中括号:‘[ ]’,括号内是索引。对于序列来说,可以使用这种方式根据索引值访问元素,对于字典来说索引就是键。
1,遍历
容器类对象都属于可迭代对象(iterable),因此都能使用for in 进行遍历。
能进行for in 遍历操作的对象是可迭代对象
from collections import Iterable
st = [5, 1, 4, 2, 3, 1]
print(isinstance(st, Iterable))
### True
下面讨论以下比较有趣的遍历:对集合set 内元素的遍历:集合set 的for in :集合内的元素都是无序的,因此遍历的时候会发现,每次遍历元素的顺序都不一样。
st = {'b', 'c', 'a', 1, 5}
for i in st:
print(i)
# 第一次运行
b
1
a
5
c
# 第二次运行
1
5
a
c
b
但是,集合内元素如果是数字的话,那么数字之间顺序是永远正序的,上面的遍历例子中,1是比5先遍历出来的,用个纯数字的集合来实验,如下:
st = {3, 4, 1, 5}
for i in st:
print(i)
###
1
3
4
5
2,成员判断: 使用成员运算符 in 来检查元素是否存在。
-
对于字典来说,使用 in 是判断字典中是否存在对应的键
>>> dt = {'name': 'marsen', 'age': 18}
>>> 'name' in dt
True
>>> 'marsen' in dt
False
# (k, v) in d 是不能实现判断键值对是否存在的功能,要实现项成员资格检查,要借助字典的方法items: (k, v)in dt.items()
>>> ('age', 18) in dt
False
>>> ('age', 18) in dt.items()
True
-
对于其它的容器对象来说都是检查对象中元素是否存在的
# 检查单个元素在容器对象中是否存在 (列表,元组,集合)
>>> lt = [0, 1, 2, 4, 5]
>>> [0, 1] in lt
False
>>> 2 in lt
True
>>> tp = (1, 2, 3)
>>> 1 in tp
True
>>> (1,) in tp
False
>>> st = {1, 2, 3, 4}
>>> 1 in st
True
>>> {1, 2} in st
False
# 对字符串来说,不仅能够检查单个字符是否存在,还能检查字串是否存在
>>> s = 'hello'
>>> 'hel' in s
True
>>> 'h' in s
True
>>> 'ho' in s
False
3,计算长度:len(container): 使用系统函数len( )返回容器内项的数量,对于字典来说,返回的就是键值对的个数
4,比较: max() /min() 以及 > < 的比较
-
最大元素和最小元素
Python中提供了内置函数max()和min(),可用于找出容器中最大和最小的元素。
>>> max((8, 1, 3, 5))
8
>>> max([1, 8, 5, 10])
10
>>> min([1, 8, 5, 10])
1
有关max和min函数的使用,请转看另外的博客,专门对这两个内置函数进行详细探讨:
max(iterable,[,key=]) / min(iterable, [,key=])
这两个内置函数的使用中,我们要注意的是迭代对象的元素之间必须是能进行大小比较的,关于大小比较的讨论下面将会进行讨论。
-
容器对象之间> <的比较
Python中不同类型的对象之间是无法进行比较的,跟整型,浮点型和复数之间的数字大小比较不同,容器类对象内包含不同的元素,它们之间就比较复杂。
首先说字符串str之间的比较,两个字符串之间的比较,首先是第一个元素进行比较,比较的原则遵循ASCII码值,如果比较出来大小,那么将确定字符串的大小,如果第一个字符是相同的,那么会接着比较第二个字符,如果一个字符串是另一个字符串的开头,那么较长的字符串为较大的。
元组之间进行比较:进行比较的时候也是先从第一个元素进行比较,比较出来结果之后,则后面的就不进行比较。
注:两个相互比较的元组之间,对应索引位置上的元素必须是同类型可比较的对象。否则会报错
>>> (100,'a')>(101,)
False
>>> (100,'a')>(100,)
True
列表和元组一样,也是先从第一个元素开始进行比较,两个列表中对应索引位置上元素都必须是同类型可比较的对象。
>>> [100, 'a']>[101]
False
>>> [100, 'a']<[100,'b']
True
上面说的是序列的大小比较操作,下面说一下剩下几个容器类的数据类型的比较:
- 集合set之间的比较是判断是否是子集,而不是比较其元素大小,大小关系就是集合之间父子集的关系
两个集合st1和st2 , 表达式st1 < st2 当st1是st2的子集, 结果才会是True
>>> {1, 3, 'a'} > {1, 3}
True
>>> {1, 3, 'a'} > {1, 3,'b'}
False
>>> {1, 3, 'a'} < {1, 3, 5,'a'}
True
- 字典dict之间是不能比较的