Python组合数据类型及其相关操作(元组、列表、字典、集合)

2021/7/16 11:05:35

本文主要是介绍Python组合数据类型及其相关操作(元组、列表、字典、集合),对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

目录

        • 注:本文中大量使用list作为列表变量名称,tuple作为元组变量名称,是取理解之便,实际应用过程中不能这样。
  • 部分应用于所有组合数据类型的函数
    • isinstance(x,y)
    • len(x)
  • 理解Python变量的指针本质
    • 指针
    • is运算符和==
  • 元组
    • 元组类型的指针本质
    • 元组、列表的索引和切片、遍历与字符串完全相同
    • 元组的其他操作
  • 列表
    • 列表a=a+b与a+=b
    • 列表相关操作
    • 列表的排序
    • 列表相关函数
    • 列表映射
    • 列表过滤
    • 列表生成式
    • 二维列表
    • 列表的拷贝
  • 字典
    • 字典的构造
    • 字典相关函数
    • 字典的遍历与深拷贝
  • 集合
    • 集合的构造
    • 集合相关函数
    • 集合相关运算

注:本文中大量使用list作为列表变量名称,tuple作为元组变量名称,是取理解之便,实际应用过程中不能这样。

部分应用于所有组合数据类型的函数

isinstance(x,y)

通过此函数判断数据x是否为y类型。如:

>>> print(isinstance(10,int))
True
>>> print(isinstance((10,7,3),tuple))
True
>>> print(isinstance("yyf&zx",float))
False

len(x)

通过此函数获得组合数据类型x的元素个数。如:

>>> print(len("string"))
6
>>> print(len((1,2,3)))
3

理解Python变量的指针本质

指针

在C语言中,可以通过指针对于指针所指内存中储存的数据直接进行操作,也是用C实现链表、树、图的重要工具。在Python语言中并没有直接提出指针概念以进行C一样的底层操作。但可将所有Python变量理解为指针(只不过在在进行打印和赋值等操作时自动*了一把)。
指针可以理解为内存的门牌号,通过一个指定的门牌号(指针)访问一个指定的房间(一块内存)。可以将指针理解为“箭头”、“钥匙”等。如:
1、将变量a赋值为10(b赋值为5),即将a这个指针指向int10;同时将变量A赋值为[1,2,3](B赋值为[4,6,6]),这是将A这个指针指向一堆指针(A[0]、A[1]…),他们分别指向其储存的内容
已执行代码:

>>>a = 10
>>>b = 5
>>>A = [1,2,3]
>>>B = [4,6,6]
>>>print(a,b,A,B)
10 5 [1,2,3] [4,6,6]

图示1:

1 2 3 4 5 6 10 a b A0 A A1 A2 B0 B B1 B2 a=10 b=5

2、将int a赋值给变量b,即将b这个指针指向a所指的地方;同时将list A赋值给B,这是将B所指的这一堆指针换成A所指的那一堆指针
已执行代码:

>>>a = 10
>>>b = 5
>>>A = [1,2,3]
>>>B = [4,6,6]
>>>print(a,b,A,B)
10 5 [1,2,3] [4,6,6]
>>>b = a
>>>B = A
>>>print(a,b,A,B)
10 10 [1,2,3] [1,2,3]

图示2:

1 2 3 10 a b A0 A A1 A2 B a=10 b=a

3、那么此时继续将a赋值为20,就是将a这个指针转而指向20,此时b仍然指向原来的10,不受影响;同时将A通过赋值语句改为[7,8,9](A=[7,8,9]),这是将A指针所指的那一堆指针直接换成另一堆,这一堆指针又分别指向7,8,9,故B不受影响
已执行代码:

>>>a = 10
>>>b = 5
>>>A = [1,2,3]
>>>B = [4,6,6]
>>>print(a,b,A,B)
10 5 [1,2,3] [4,6,6]
>>>b = a
>>>B = A
>>>print(a,b,A,B)
10 10 [1,2,3] [1,2,3]
>>>a = 20
>>>A = [7,8,9]
>>>print(a,,b,A,B)
20 10 [7,8,9] [1,2,3]

图示3:

1 2 3 7 8 9 10 20 b a B0 B B1 B2 A0_ A A1_ A2_ a=20 这里的B0、B1、B2其实就是上附幅图的A0、A1、A2 这里的A0_等与上幅图的A0等毫无关系,加_以示区别

4、在3中,我们通过赋值语句A=[7,8,9]直接改变了A指针所指的一堆指针,B不受影响;如果不进行这样(3)的操作,转而进行改变列表元素的操作A[0]=10,这是将A指向的原来指向1的A0指针重新指向10,所以B也会受到改变
已执行代码:

>>>a = 10
>>>b = 5
>>>A = [1,2,3]
>>>B = [4,6,6]
>>>print(a,b,A,B)
10 5 [1,2,3] [4,6,6]
>>>b = a
>>>B = A
>>>print(a,b,A,B)
10 10 [1,2,3] [1,2,3]
>>>A[0] = 10
>>> print(A,B)
[10, 2, 3] [10, 2, 3]

图示4:

2 3 10 A0 A A1 A2 B A0=10

is运算符和==

a==b返回一个真值,若为Ture代表a和b所指地址所放的内容相同;a is b同样返回一个真值,若为Ture代表a与b指向同一个地方。如:

>>> a=[1,2,1]
>>> b=[1,2,1]
>>> print(a is b,a==b)
False True
>>> c=d=[1,2,1]
>>> print(c is d,c==d)
True True

再如:

>>> a=10
>>> b=10
>>> print(a is b,a==b)
True True
>>> c="string"
>>> d="string"
>>> print(c is d,c==d)
True True

为何同样是先用一样内容的东西给a和b赋值,用list类型(dict、set也是)打印a is b为True,而用int类型(float、complex、str、tuple也是)打印a is b为False?
这是因为,a=10;b=10;的操作将a指向一个10,将b指向一个10,而计算机中常量10只有一个,所以(a is b)=True;而进行A=[1,2,1];B=[1,2,1];的操作时,A和B分别指向一片储存着一堆指针的内存地址,这两片内存不同,只是这两片内存中的两堆地址指向的1,2,1常量相同,所以(A is B)=False(可参见上面的图示)。
所以,对于int、float、complex、str、tuple类型的变量,不必关注is和==的区别,因为这些类型本身并不可改变,不会出现改变了a的指向b也跟着变的情况,其中int、float、complex、str类型,a is b和a==b等价。而对于list、set、dict类型则要格外注意is和==的区别

元组

Python中的元组数据类型是由数个逗号分隔的元素(类型不限)组成,前后可加圆括号,元组不能修改(不增、不减、不改(不能对元素进行赋值操作)、不排(不能修改顺序))。

元组类型的指针本质

元组类型的每一个元素都可以看作指针,元组元素不可修改指的是不可以改变每个元组元素(指针)的指向,但这些元素指向的内容是可以被修改的。 如:

>>> tup=(10,"string",[1,2,3],{1:100},None)
>>> tup[0]=1
Traceback (most recent call last):		#我们看到对元组元素进行赋值会报错
  File "<stdin>", line 1, in <module>
TypeError: 'tuple' object does not support item assignment
>>> tup[2][0]=10						#但可修改列表类型元素的内容
>>> print(tup)
(10, 'string', [10, 2, 3], {1: 100}, None)

元组、列表的索引和切片、遍历与字符串完全相同

字符串可参考此链接

元组的其他操作

tup*n或n*tup将tup复制n次
tup1=tup2+tup3新建一个元组tup1为tup2和tup3连接后的样子
tup+=tup_sub新建一个元组仍命名为tup,为原tup和tup_sub连接后的样子
元组之间比大小逐个元素相比,直至分出大小,若有对应元素之间不可比,则runtime error
tuple()将其他数据类型转为类型

列表

Python语言中,列表数据类型是由逗号分隔开的各个元素加上方括号,列表元素可以是任何类型。

列表a=a+b与a+=b

a=a+b是重新对a进赋值,而a+=b是在a后方添加b的所有元素。如:

>>> a=b=[1,2,3]
>>> a+=[4]		
>>> print(a,b)		#a和b指向同一地方,改变a内容即改变b内容
[1, 2, 3, 4] [1, 2, 3, 4]
>>> a=a+[5]
>>> print(a,b)		#对a进行重新赋值,从此与b分道扬镳
[1, 2, 3, 4, 5] [1, 2, 3, 4]

列表相关操作

+通过a+b将两个列表相连接
list*n或n*list表示将list的所有元素复制n次
列表比大小元素逐个相比,直至分出大小,若有两个对应元素无法比较,则runtime error

列表的排序

排序问题:有N个元素的列表,想要让它所有的元素依据某一特定顺序排列。排序有很多种,插入排序、冒泡排序、快速排序、归并排序、堆排序、桶排序等。下面介绍Python封装好的排序函数,list.sort()和sorted()其时间复杂度为O(N*logN),为稳定排序
1、直接使用list.sort()将所有元素从小到大排序。如:

>>> list=["yyf","yt","yfz","hgj"]
>>> list.sort()
>>> print(list)
['hgj', 'yfz', 'yt', 'yyf']

2、直接使用LIST=sorted(list)函数得到list从小到大排序后的结果,但不改变list。如:

>>> list=[9,8,7,6,5,4,3,2,1]
>>> LIST=sorted(list)
>>> print(list,LIST)
[9, 8, 7, 6, 5, 4, 3, 2, 1] [1, 2, 3, 4, 5, 6, 7, 8, 9]

3、通过自定义关键字函数key实现更加复杂的排序操作。list.sort(key)中的key函数为关键字函数默认为lambda x: x,该函数在排序时将列表中每一个元素作为参数,返回值作为排序的关键字,即排序的依据。如:

>>> list=[(1,2,3),(1,1,1),(10,-100,0),(1,2,2)]
>>> def myKey(x):		#即将每个元组的所有元素之和作为关键字
...     return sum(x)
>>> list.sort(key=myKey)
>>> print(list)
[(10, -100, 0), (1, 1, 1), (1, 2, 2), (1, 2, 3)]

4、当然sorted()中我们也可以添加自定义的关键字函数参数来实现自定义的排序。如:

>>> list=[(1,2,3),(1,1,1),(10,-100,0),(1,2,2)]
>>> def myKey(x):		#这里我们将每个元组的第一个元素当作关键字
...     return x[0]
>>> LIST=sorted(list,key=myKey)
>>> print(list,LIST)
[(1, 2, 3), (1, 1, 1), (10, -100, 0), (1, 2, 2)] [(1, 2, 3), (1, 1, 1), (1, 2, 2), (10, -100, 0)]

5、通过改变reverse参数实现从大到小排序。list.sort()和sorted()函数中reverse参数默认为False,表示从小到大排序;将其改为Ture即可从大到小排序。

>>> list=[1,2,3,0,6,4,5]
>>> list.sort()
>>> print(a)
[1, 2, 3, 4, 5]
>>> list.sort(reverse=True)
>>> print(list)
[6, 5, 4, 3, 2, 1, 0]

列表相关函数

del(关键字)删除元素,如,del list[0]
list.append(x)将x当作一个元素加在list最尾处
sum(list)求和函数,各元素求和
list.count(x)返回列表中x的个数(作为元素的x)
list.extend(x)添加列表x在列表list尾处,功能同+=
list.insert(i,x)将x作为元素添加在下标为i处
list.remove(x)删除元素x,若x不在列表中,引发异常
list.reverse()将list颠倒
list.index(x)查找x,返回第一次找到的下标,找不到引发异常
list.index(x,s)从下标为s处开始实现inde(x)功能
list()将其他类型数据转为列表类型

列表映射

map(function,sequence)函数可将一个序列映射到另一个序列,其映射规则由参数function函数决定,参数sequence为映射前序列,返回一个延时求值对象,可以通过tuple()、list()等函数将其转换成元组、列表等类型。如:

>>> def f(x):
...     print("f函数执行次数++")
...     return x**2
>>> a=map(f,[1,2,3,4])		#此时函数f()并未执行,a是延时求值对象
>>> print(list(a))			#将a转为list类型时,f()才开始执行,将sequence中元素依次当作参数传入,返回同样类型的变量
f函数执行次数++				#当然python并不支持++语法
f函数执行次数++
f函数执行次数++
f函数执行次数++
[1, 4, 9, 16]

列表映射可配合其他函数用于输入,如:

>>> a,b,c=map(int,input().split())
1 2 3		#这是输入
>>> print(a,b,c)
1 2 3

列表过滤

filter(function,sequence)函数,作用是抽取序列中使得function(x)为True的元素x,返回一个延时求值对象。如:

#该段代码实现抽取列表l中个位数为1的元素
>>> l=[1,11,111,2,3,4,51,6,71]
>>> L=list(filter(lambda x:x%10==1,l))
>>> print(L)
[1, 11, 111, 51, 71]

列表生成式

当需要生成元素具有一定规律但又很多的列表时,既可以采用循环加append的方式,也可以采用更为简洁的列表生成式。

>>> l=[x**2 for x in range(10)]							#简单生成
>>> print(l)
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
>>> l=[x*y for x in range(5) for y in range(5,10)]		#双重循环
>>> print(l)
[0, 0, 0, 0, 0, 5, 6, 7, 8, 9, 10, 12, 14, 16, 18, 15, 18, 21, 24, 27, 20, 24, 28, 32, 36]
>>> l=[x**2 for x in range(10) if x%2==0]				#加上判断语句
>>> print(l)
[0, 4, 16, 36, 64]

二维列表

二维列表即可看作矩阵,a[i][j]即为第i行第j列的元素(行优先)。定义二维数组的方法:1、通过append(一个列表)的方式2、借助列表生成式3、直接定义。如:

>>> li=[]												#1
>>> for i in range(3):
...     li.append([0]*4)
>>> print(li)
[[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]

>>> li=[[0 for i in range(4)] for j in range(3)]		#2
>>> print(li)
[[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]

>>>li=[[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]		#3
>>>print(li)
[[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]

#但不可通过这样的方式定义
>>> l=[0]*4
>>> li=[l]*3
>>> print(li)
[[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]
#看起来也是一个4乘3的矩阵吗,但由于生成时从[l]*3而来,所有li中的三个元素实际上指向内容相同
#若修改li[0][0],li[1][0],li[2][0]、l[0]都会发生改变
>>> li[0][0]=100
>>> print(li,l)
[[100, 0, 0, 0], [100, 0, 0, 0], [100, 0, 0, 0]] [100, 0, 0, 0]

列表的拷贝

1、似乎拷贝仅仅是a=b的事,如:

>>> a=[1,2,3]
>>> b=a

但结合变量的指针实质来看,这样仅仅导致了上文图示2的效果。

>>> a[0]=100
>>> print(a,b)
[100, 2, 3] [100, 2, 3]

所有这样并未拷贝任何东西,毫无意义,反而导致变量名称冗余。
2、切片拷贝
我们通过切片操作来进行列表每个元素指针的拷贝(b=a[:]),这样就新生成了一堆不同的指针指向最初列表指针指向的地方,但只拷贝了指针未拷贝指针所指内容,仍然未进行深拷贝(彻底完全拷贝)

>>> a=[1,[2,3]]
>>> b=a[:]
>>> b.append(4)
>>> print(a,b)			#a,b看似已经分开
[1, [2, 3]] [1, [2, 3], 4]
>>> b[1][0]=200
>>> print(a,b)			#其实并没有,“第一层已经分开,第二层却还一样”
[1, [200, 3]] [1, [200, 3], 4]

执行完后的样子:

1 3 4 200 a0 a a1 a1_0 a1_1 b0 b b1 b2

3、利用copy库进行深拷贝。
利用copy库中的copy.deepcopy()函数可以进行真正意义上的深拷贝。既拷贝指针又拷贝指针所指内容,让a和b完全脱离。如:

>>> import copy
>>> a=[1,[2,3]]
>>> b=copy.deepcopy(a)
>>> print(a,b)
[1, [2, 3]] [1, [2, 3]]
>>> a.append(4)
>>> b[1][0]=200
>>> print(a,b)
[1, [2, 3], 4] [1, [200, 3]]

字典

Python语言中,字典数据类型的每个元素由键和值两部分组成,形式如:“key:value”,可以根据键对值进行快速查找(若查找的键不存在,引发异常)。如:

>>>d = {key1:value1,key2:value2}
>>> d={1:"yyf",2:"fff",3:"yyy",4:"ffy"}
>>> print(d[1])
yyf

字典所有元素的键必须不同(内容不同),键也必须是不可变的数据类型,如str、tuple、int、float、complex。
可以添加元素、对元素的进行修改删除元素,如:

>>> d={1:"yyf",2:"fff",3:"yyy"}
>>>d[4]="ffy"		#添加元素
>>>d[1]="YYF"		#修改值
>>>print(d)
{1:"YYF",2:"fff",3:"yyy",4:"ffy"}
>>>del d[4]			#删除元素
>>>print(d)
{1:"YYF",2:"fff",3:"yyy"}
>>>print(1 in d)	#判断是否有元素键为1
True

字典的构造

字典可直接构造或使用dict()函数,如:

>>> d={1:10,2:20,3:30}		#直接赋值构造
>>> print(d)
{1: 10, 2: 20, 3: 30}
>>> d=dict(name="BOB",age=12,height=2.22)		#通过dict()构造
>>> print(d)
{'name': 'BOB', 'age': 12, 'height': 2.22}
>>> d=dict([(1,100),(2,200)])
>>> print(d)
{1: 100, 2: 200}

字典相关函数

get(key,v)若键key存在,返回其值,否则返回v
clear()清空
keys()取键的序列
values()取值的序列
items()取元素的序列
pop(x)删除键为x的元素,没有则引发异常
copy()浅拷贝

字典的遍历与深拷贝

可以通过上述keys()、values()、items()函数生成的序列便利字典。注意,这些序列既不是list、也不是tuple、dict、set等。另外,字典元素的顺序值得注意:在python3.5及以前的版本,字典元素无顺序;在python3.6及以后的版本,字典元素的顺序与元素加入字典时的顺序相同。
字典实现深拷贝的途径与list相同,即copy.deepcopy()

集合

Python语言中集合数据类型的概念与数学上集合概念相同。具有如下特点:集合元素互异、集合元素无序、集合元素只能是不可变的数据类型(int、float、complex、tuple、str),其中tuple中如含有可变数据类型,也不能作为集合元素。集合的作用往往是判断一个东西是否在一堆东西里面

集合的构造

集合可直接定义,也可通过set()函数将其他类型变量转为集合。如:

>>> s={1,2,3,4,2,5}				#直接定义,会自动去重
>>> print(s)
{1, 2, 3, 4, 5}
>>> s=set([1,2,3,4,5,6,4,8])	#通过set()定义
>>> print(s)
{1, 2, 3, 4, 5, 6, 8}
>>> s=set({1:10,2:20})			#字典类型只取其键
>>> print(s)
{1, 2}
>>> s=set("string")
>>> print(s)
{'t', 'i', 's', 'r', 'n', 'g'}

集合相关函数

clear()清空
add(x)将x作为元素添加进集合
update(x)将序列x中所有元素加入集合
copy()浅拷贝
remove(x)删除元素x,若没有则引发异常

集合相关运算

与数学上集合概念相同,Python中集合数据类型也可进行交并等运算。如:
a,b是集合

x in a返回真值,x是否在a中
a|b
a&b
a-b差,在a中而不在b中的元素组成的集合
a^ba与b的对称差,即(a|b)-(a&b)
a==ba、b是否一样
a!=ba、b是否不一样
a<=b(b>=a)a是否是b的子集
a<b(b>a)a是否是b的真子集


这篇关于Python组合数据类型及其相关操作(元组、列表、字典、集合)的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程