7.5 Python中的构造类型变量

所谓“构造类型”,就是将不同基本类型的数据组合在一起构成的新数据类型,类似于C语言中的结构体等类型。Python中的构造类型主要包括:

· 序列[包括字符串(String)、列表(List)和元组(Tuple)]。

· 映射[字典(Dictionary)]。

· 集合(Set)。

7.5.1 字符串

字符串是由一个或多个字符组成的序列,它是Python中使用极为普遍的数据类型之一。Python不支持单字符类型,单字符在Python中也被视为字符串。

1.字符串变量的定义

定义字符串变量的语法如下(通过举例加以说明):

>>> v1=’我要学好Python'
>>> v2="我能学好Python"
>>> v3='''
我要学好Python
我能学好Python
'''
>>> print(v1)
我要学好Python
>>> print(v2)
我能学好Python
>>> print(v3)

我要学好Python
我能学好Python

>>>

在上述程序中,分别用3种不同的方式定义了3个字符串变量:v1、v2、v3。其中,v3是多行字符串变量。

除此之外,字符串变量还可以通过相互赋值加以定义,举例如下:

>>> v4=v2
>>> print(v4)
我能学好Python
>>>

上述程序通过将v2的值赋给v4,从而定义了字符串变量v4。

归纳起来,在Python中,通常采用以上4种方式定义字符串变量。

2.字符串的特点

字符串中的元素是不可变的,这是字符串最大的特点。

例如,以下程序欲将字符串的第二个字符由b改为B。

>>> ss="abcdef"
>>> ss[1]='B'
Traceback (most recent call last):
  File "<pyshell#65>", line 1, in <module>
    ss[1]='B'
TypeError: 'str' object does not support item assignment
>>>

程序中定义了一个字符串变量ss,希望修改下标为1的元素,将它由b改为B。但在程序运行后抛出异常,异常类型是:str对象不支持修改。

3.字符串的使用

可以使用方括号[]访问字符串中的子字符串。方括号内的数字表示下标,下标从0开始。

举例如下:

>>> msg='Amazing Python! '
>>> print(msg)
Amazing Python!
>>> print(msg[0:])
Amazing Python!
>>> print(msg[:4])
Amaz
>>> print(msg[1:5])
mazi
>>>

由此可见,字符串元素的下标是从0开始的。

截取子字符串的方法是:

字符串变量[起始下标:结束下标]

其中,起始下标默认为0,可省略;结束下标表示要截取字符串的最后一个字符加1,也就是说,截取的子字符串不包括结束下标对应的元素。Python将这个过程称为“切片(Slice)”。

下标可为负数,它表示从字符串的尾部逆向访问字符串,最后一个元素的下标对应为-1。依次类推,倒数第二个元素的下标为-2。与正向截取子字符串相同的是,逆向截取的子字符串也不包括结束下标对应的元素。

举例说明如下:

>>> msg='This is a test string! '
>>> print(msg[:-1])
This is a test string
>>> print(msg[:-0])

>>> print(msg[-1:])
!
>>> print(msg[0:-3])
This is a test stri
>>>

由以上程序可知,不允许直接对字符串中的元素进行修改。那么,在何种情况下可以修改字符串中的元素呢?可对已存在的字符串进行修改,但它必须被赋给另一个变量。也就是说,要改变一个字符串中的元素,必须新建一个字符串变量。

以下这样做是不被允许的:

>>> msg='Hello, world! '
>>> msg[6]="W"
Traceback (most recent call last):
  File "<pyshell#48>", line 1, in <module>
    msg[6]="W"
TypeError: 'str' object does not support item assignment
>>>

但是,可将修改后的字符串赋给另一个字符串变量。

>>> msg1='Hello, world! '
>>> msg2=msg1[:6]
>>> msg1='Hello, world! '
>>> msg2=msg1[:6]+'Python! '
>>> print(msg2)
Hello, Python!
>>>

归纳起来,字符串中下标的用法有以下几种形式。

· string[0:-1]):从头到尾。

· string[2:]):从下标2开始到尾。

· string[2:6]):从下标2到下标(6-1)。

4.字符串的重复输出

字符串可被重复输出,其方法如下:

字符串*n

其中,n代表重复输出的次数,它必须是一个整数。

例如:

print(string*2)  #输出两次
print("*"*10)   #输出10个*

7.5.2 列表

列表是一种不同数据类型元素的有序集合。与元组和字符串不同的是,列表中的元素是可变的,也就是可以随时添加或删除其中的元素。

列表通过方括号“[]”加以表示。

1.列表变量的定义

1)定义列表变量的一般方法

列表变量的定义方法如下:

列表变量 = [元素1,元素2,元素3, …]

其中,每个元素的类型可以各不相同,但它们被依次存储,也就是说,其下标是固定的,起始下标为0。

举例说明列表变量的定义:

#ListDemo.py
listDemo=["aa",1, "bb",2]
print(listDemo)
print(listDemo[0])           #输出下标为0的元素
print(listDemo[2:])           #输出从下标2开始到尾的元素
print(listDemo[1:3])          #输出从下标2到下标(n-1)的元素
print(listDemo*2)           #输出两次
listDemo[0]="替换的"
print(listDemo)             #修改后的

运行上述程序后,结果如下:

['aa', 1, 'bb', 2]
aa
['bb', 2]
[1, 'bb']
['aa', 1, 'bb', 2, 'aa', 1, 'bb', 2]
[’替换的’, 1, 'bb', 2]
>>>

2)通过list()定义列表变量

可以通过内置函数list()将字符串定义为列表变量。

举例如下:

>>> mylist=list('hello')
>>> mylist
['h', 'e', 'l', 'l', 'o']
>>>

2.列表的使用

与字符串相同,列表也可通过下标法进行访问。当正向访问时,下标从0开始,也可从尾部逆向访问,最后一个列表元素的下标为-1。对列表进行操作时一定要避免越界。所谓“越界”,是指超出下标范围。

举例如下:

>>> mylist=list('hello')
>>> mylist
['h', 'e', 'l', 'l', 'o']
>>> mylist[-1]
'o'
>>> mylist[1:3]
['e', 'l']
>>>

在截取列表元素时,可使用以下形式:

列表[m:n]

但一定要注意,在截取的元素中,只包括从下标m开始至下标(n-1)的部分,不包括下标n对应的元素。此特性适用于字符串、列表和元组3种序列型数据。

1)添加新元素

使用append()方法可把新元素追加到列表的尾部;而使用insert()方法则可将新元素添加到特定的位置。

2)删除元素

删除元素可采用pop()方法。执行L.pop()命令可删除列表L中的最后一个元素。如果要删除特定位置的元素,则可以采用pop(2)的形式,其中参数2表示的是位置,即下标。

3)替换

列表中的元素可被方便地替换,替换操作可直接使用下标法。例如:

>>> mm[3]=mm[3]+1

该语句通过下标法将列表中下标为3的元素在原值的基础上增加1。

4)遍历打印

通过for语句可实现对列表的遍历访问。举例如下:

>>> L = ['a', 'b', 'c']
>>> for i in L:
    print(i)
a
b
c

3.列表的特点

列表中的元素是可变的,这是列表有别于元组的最大特点。举例如下:

>>> mylist=list('hello')
>>> mylist
['h', 'e', 'l', 'l', 'o']
>>> mylist[-1]
'o'
>>> mylist[1:3]
['e', 'l']
>>> mylist[0]='H'
>>> mylist
['H', 'e', 'l', 'l', 'o']
>>>

7.5.3 元组

1.什么是元组

元组是另一种有序列表,可将元组理解成一种不可变的列表。

元组和列表非常类似,但是,元组一旦被初始化,就不能被修改。那么,不可变的元组有何意义?元组的意义在于,因为元组是不可变的,所以在某些场合使用元组可以提高代码的安全性。因此,笔者建议,凡能用元组代替的变量应尽可能地使用元组,而不要使用列表。

2.如何定义元组变量

元组通过括号“()”加以表示。

1)元组变量的定义

定义元组变量的语法如下:

元组变量 = (元素1,元素2,元素3, …)

其中,每个元素的类型可以各不相同。

举例如下:

# TupleDemo.py
tupleDemo=("aa",1, "bb",2)
print(tupleDemo)
print(tupleDemo[0])          #输出下标为0的元素
print(tupleDemo[2:])         #输出从下标2开始到尾的元素
print(tupleDemo[1:3])         #输出从下标1到下标(3-1)的元素
print(tupleDemo*2)          #输出两次

在上述程序中,第一条语句为tupleDemo=("aa",1, "bb",2),它定义了一个名为tupleDemo的元组变量,共有4个元素,它们各自有不同的类型,分别是字符串、整数、字符串、整数。

运行上述程序后,输出结果如下:

('aa', 1, 'bb', 2)
aa
('bb', 2)
(1, 'bb')
('aa', 1, 'bb', 2, 'aa', 1, 'bb', 2)
>>>

通过将程序与输出结果对照分析,不难理解元组定义与使用的一般方法。

2)空元组的定义

空元组的定义如下:

tupleDemo=()              #空元组

3)定义只有一个元素的元组

定义只有一个元素的元组:

tupleDemo=(a, )             #一个元素

必须在元素之后加上“, ”,否则,定义的不是元组,而是一个普通变量。

举例如下:

>>> tupledemo=(1, )
>>> print(tupledemo)
(1, )
>>> tupledemo=(1)
>>> print(tupledemo)
1
>>>

3.元组的特点

元组中的元素是不可变的。

如何真正理解元组的这个特性呢?举例说明如下:

t = ('a', 'b', ['A', 'B'])
t[2][0] = 'X'
t[2][1] = 'Y'
t[0]='b'
print(t)

在上述程序中,第一条语句定义了一个元组变量t,其中第三个元素为列表。第四条语句试图将元组的第一个元素由’a’改为’b'。

运行上述程序后,得到的结果如下:

Traceback (most recent call last):
  File "C:/Users/Administrator/Desktop/hhfgh.py", line 4, in <module>
    t[0]='b'
TypeError: 'tuple' object does not support item assignment
>>>

由此可见,第四条语句出错了。

如果将第四条语句删除,改为如下程序:

t = ('a', 'b', ['A', 'B'])
t[2][0] = 'X'
t[2][1] = 'Y'
print(t)

运行上述程序,一切正常并得到如下结果:

('a', 'b', ['X', 'Y'])
>>>

上述举例说明,元组中的元素是不可变的,但是,由于第三个元素是列表,而列表是可变的,所以第二、三条语句是正常的。注意,千万不能将此理解成元组中的元素是可变的。

举例如下:

t = ('a', 'b', ['A', 'B'])
t[2]=3
print(t)

上述程序中的第二条语句试图将第三个元素由列表改为整型,运行上述程序,程序出错了。

Traceback (most recent call last):
  File "C:/Users/Administrator/Desktop/hhfgh.py", line 2, in <module>
    t[2]=3
TypeError: 'tuple' object does not support item assignment
>>>

出错的原因是:'tuple' object does not support item assignment。将它翻译成中文就是“元组不支持修改”。

4.元组的使用

直接使用下标索引。

举例如下:

>>> t=(6,7,8)
>>> t[1]
7
>>>

在元组中,虽然元素不可被修改,但是可通过运算符“+”对两个元组进行连接组合。举例如下:

>>> t1=(6,7,8)
>>> t2=(-1,0,1)
>>> t3=t1+t2
>>> t3
(6, 7, 8, -1, 0, 1)
>>> t3=t2+t1
>>> t3
(-1, 0, 1, 6, 7, 8)
>>>

实际上,“+”运算的作用远不止这一个。请看:

>>> aa=(1,2,3)
>>> bb=(4,5,6)
>>> cc=aa+bb
>>> cc
(1, 2, 3, 4, 5, 6)
>>> aa="123"
>>> bb="456"
>>> cc=aa+bb
>>> cc
'123456'
>>> aa=[1,2,3]
>>> bb=[4,5,6]
>>> cc=aa+bb
>>> cc
[1, 2, 3, 4, 5, 6]
>>>

除此之外,在上面的举例中,曾涉及元组的重复输出,重复输出的方法与字符串重复输出的方法非常相似。事实上,列表也可以重复输出。举例如下:

>>> mytuple=("1",2, "abc")
>>>print(mytuple*2) #重复输出元组两次
('1', 2, 'abc', '1', 2, 'abc')
>>> mylist=[1,2,3]
>>>print(mylist*2)  #重复输出列表两次
[1, 2, 3, 1, 2, 3]
>>>

7.5.4 集合

1.什么是集合

集合是一系列无序的、不重复的元素的组合体,集合中的每个元素可为不同的类型。因此,集合可被看成数学意义上的无序、无重复元素的集合。

2.集合变量的定义

集合通过“{}”加以表示。

常用以下3种方法定义集合变量。

第一种——直接定义。

>>> setdemo={1, "ab",7.8}
>>> print("第一种方法定义的集合:", setdemo)
第一种方法定义的集合: {1, 'ab',7.8}
>>>

第二种——通过列表和set()函数定义集合变量。

>>> vlist=[12,78,56,12,66,78]
>>> vset=set(vlist)
>>> vset
{56, 66, 12, 78}
>>>

在上述程序中,首先定义一个列表变量,然后通过内置函数set()将列表转换为集合。由于集合类型具有不重复和无序的特性,所以,从举例中可见,列表中的重复元素被删除,元素的顺序关系被忽略。

第三种——通过add()方法对已定义的空集合进行添加。

>>> sdemo=set()
>>> sdemo.add(23)
>>> sdemo.add(12)
>>> sdemo.add("abc")
>>> sdemo
{'abc', 12, 23}
>>> sdemo.add(23)
>>> sdemo
{'abc', 12, 23}
>>>

在上述程序中,首先通过set()函数定义一个空集合对象,然后通过对象的内置方法add()进行元素添加,在添加过程中如果出现相同的元素则被忽略。例如,两次添加23,但是第二次添加被忽略。

3.集合的使用

1)两个集合的运算

两个集合可进行交集、并集、差集等运算。

举例如下:

setDemo1={"a",23}
setDemo2={"a", "b"}
print("集合B ", setDemo2)
print("AB的差集 ", setDemo1-setDemo2)
print("AB的并集 ", setDemo1|setDemo2)
print("AB的交集 ", setDemo1&setDemo2)
print("AB的不同时存在的 ", setDemo1^setDemo2)

运行上述程序后,得到的结果如下:

集合B  {'b', 'a'}
AB的差集  {23}
AB的并集  {'b', 'a',23}
AB的交集  {'a'}
AB的不同时存在的  {'b',23}
>>>

2)添加、删除集合中的元素

对集合对象可进行添加元素、删除元素、随机删除元素并获得该元素等操作。

· 添加的方法:add()内置方法。

· 删除的方法:discard()、remove()、pop()等内置方法。要注意三者的区别。

· 删除集合中所有元素的方法:clear()内置方法。

4.集合的特点

集合中的元素是无序的、不可重复的,即不允许在集合对象中出现两个及以上的相同元素。举例如下:

>>> set1={11,15,17,18}
>>> set2={11, "a",67.8, "bc"}
>>> set3={11,12,12,17}
>>> set3
{17, 11, 12}
>>>

上述程序表明,在定义集合变量set3时使用了两个相同的元素,虽然这在语法上被允许,但是从实际结果来看,两个相同的元素(重复)是不被接受的。

7.5.5 字典

1.什么是字典

字典是一个存放无序的键/值(key/value)映射类型数据的容器。

字典的键可为数字、字符串或元组,键必须是唯一的。在Python中,数字、字符串和元组均为不可变类型,而列表、集合是可变类型,所以列表和集合不能作为字典的键。键必须为不可变类型,而值则可为任意类型。

2.字典变量的定义

字典通过“{}”加以定义。这一点与集合是一样的,但要注意两者的区别。

定义字典变量的方法如下:

字典变量 = {键1:值1,键2:值2,键3:值3, …}

举例如下:

>>> ddemo={"name":"shenhongwei", "sex":'M', "year":52}
>>> ddemo
{'name': 'shenhongwei', 'sex': 'M', 'year': 52}
>>>

在上述举例中,定义了一个字典变量ddemo,它有3个键值对。

还有一种方法可定义字典变量:首先创建空字典对象,然后逐一添加键值对,从而定义字典变量。

举例如下:

>>> ddemo1={}
>>> ddemo1["a"]=12
>>> ddemo1["b"]=13
>>> ddemo1["c"]=14
>>> ddemo1
{'a': 12, 'b': 13, 'c': 14}
>>>

在上述程序中,首先创建空字典变量ddemo1,然后分3次逐一添加键值对,从而定义字典变量ddemo1。注意,添加时必须以键为关键字。

3.字典的使用

字典是通过键(key)作为索引来访问和操作值(value)的。特别要引起注意的是,字典一旦被定义,它的键不能被修改,而值可以被修改。

修改值的具体方法如下:

字典[key]

举例1:

ddemo={"name":"shenhongwei", "sex":'M', "year":52}
print(ddemo)
print(ddemo["name"])

上述程序被运行后,得到的结果如下:

{'name': 'shenhongwei', 'sex': 'M', 'year': 52}
shenhongwei

首先输出整个字典,然后通过键索引方式索引键“name”,从而输出其对应的值“shenhongwei”。

举例2:
>>> ddemo1={'a': 13, 'b': 13, 'c': 14}
>>> ddemo1["c"]=15
>>> ddemo1
{'a': 13, 'b': 13, 'c': 15}
>>>

通过键“c”将它对应的值由14改为15。

举例3:

>>> ddemo1={'a': 13, 'b': 13, 'c': 14}
>>> x=ddemo1.pop("c")
>>> print(ddemo1)
{'a': 13, 'b': 13}
>>> print(x)
14
>>>

上述程序移除键“c”,返回其对应的值并赋给变量x, x的值为14。此处使用了内置方法pop(),从中可了解该方法的具体用法。

举例4:

>>> ddemo1={'a': 13, 'b': 13, 'c': 14}
>>> print(ddemo1.keys())
dict_keys(['a', 'b', 'c'])
>>> print(ddemo1.values())
dict_values([13, 13, 14])
>>>

上述程序首先定义一个字典变量ddemo1,然后通过方法keys()和values()得到它的全部键和值。这两个方法的返回值均为列表形式。

举例5:

>>> ddemo1={'a': 13, 'b': 13, 'c': 14}
>>> for i in ddemo1.keys():
    print(i)

a
b
c
>>>

4.字典的特点

(1)字典的第一个特点是查找速度快,而且查找的速度与元素的个数无关;而列表的查找速度是随着元素的增加而逐渐下降的。

(2)字典的第二个特点是存储的键值对是无序的。

(3)字典的第三个特点是键的数据类型必须是不可变的类型,所以列表和集合不能作为字典的键。

(4)字典的第四个特点是占用的内存空间大。