2015/9/4 Python基础(8):映射和集合类型

时间:2021-12-07 20:42:57

Python里唯一的映射类型是字典。
映射类型对象里,hash值(key)和指向的对象(值)是一对多的关系。
字典对象是可变的,这一点上很像列表,它也可以存储任意个数任意类型的Python对象,其中包括容器类型。字典类型和序列类型的区别是存储和访问数据的方式不同。序列类型只用数字类型的键(从序列开始按数值顺序索引。)映射类型的键(key)可以是其他的对象类型(一般是字符串),映射类型的键直接或间接地和存储的数据值相关联。而在映射类型中,数据是无序排列的。

一个字典条目的语法格式是 键:值。 多条字典条目被包含在{}里。
创建字典和赋值

>>> dict1 = {}
>>> dict2 = {1:80, 'string':'sss', 2.3:['list']}
>>> dict1,dict2
({}, {
1: 80, 'string': 'sss', 2.3: ['list']})
>>> dict3 = dict((['x',1],['y',2]))
>>> dict3
{
'y': 2, 'x': 1}

 

访问字典中的值
遍历一个字典,只需要循环查看它的键

>>> for key in dict2.keys():
print 'key = %s, value = %s' % (key, dict2[key])

key
= 1, value = 80
key
= string, value = sss
key
= 2.3, value = ['list']

 

也可以不用keys()方法,用迭代器来访问:

>>> for i in dict2:
print 'key = %s, value = %s' % (i, dict2[i])


key
= 1, value = 80
key
= string, value = sss
key
= 2.3, value = ['list']

 

要得到字典里的某个元素的值,使用字典[键]的方式:

>>> dict2 = {1:80, 'string':'sss', 2.3:['list']}
>>> dict2['string']
'sss'
>>> dict2[string]

Traceback (most recent call last):
File
"<pyshell#2>", line 1, in <module>
dict2[string]
NameError: name
'string' is not defined

 

如果没有对应的键,就会报错。
判断一个字典中是否有某个键可以用in 以及 not in操作符

>>> 1 in dict2
True
>>> 'sss' in dict2
False

 

字典中的键不允许改变,所以我们用数字和字符串作为键,列表和其他字典不允许作为键。

映射类型操作符
字典可以和所有标注类型操作符一起工作但不支持拼接和重复一类的操作。
字典的键查找操作符[]是唯一仅用于字典的操作符,它和切片操作符很相像,但是[]里不只是数字索引。

字典的比较cmp(dict1, dict2)
先比较字典的长度(键的数量),再比较字典的键,再比较字典的值,然后是完全匹配。

映射类型相关函数
dict()
如果不提供参数,会生成空字典。当容器类型对象作为一个参数传递给dict()时,如果参数是可迭代的,那么这个序列必须是成对出现的。每个值的对中,第一个元素是键,第二个元素是值。如果输入参数是(另)一个映射对象,对其调用dict()会从存在的字典里复制内容来生成新的字典。新生成的字典是原来字典的浅复制,它与用copy()方法生成的字典对象一样,但是比用copy()方法慢。

>>> dict(zip(('x', 'y'), (1, 2)))
{
'y': 2, 'x': 1}
>>> dict([['x', 1], ['y', 2]])
{
'y': 2, 'x': 1}
>>> dict([('xy'[i-1], i) for i in range(1,3)])
{
'y': 2, 'x': 1}
>>> dict(x=1, y=2)
{
'y': 2, 'x': 1}
>>> dict8 = dict(x=1, y=2)
>>> dict8
{
'y': 2, 'x': 1}
>>> dict9 = dict(**dict8)
>>> dict9
{
'y': 2, 'x': 1}
>>> dict9 = dict8.copy()
>>> dict9
{
'y': 2, 'x': 1}

 

hash()
hash()本身不是为字典设计的方法,但它可以判断一个对象是否可以做字典的键。只有这个对象是可哈希的,才可以作为字典的键(函数的返回值是整数,不产生错误和异常)
如果用比较操作符比较两个数值,发现它们相等,那么即使两者数据类型不同,也会得到相同的哈希值。
如果是非可哈希对象作为参数,会产生TypeError错误。

函数 操作
dict([container]) 创建字典的工厂函数。如果提供了容器类(container) , 就
用其中的条目填充字典,否则就创建一个空字典。
len(mapping) 返回映射的长度(键-值对的个数)

映射类型的内建方法

方法名字 操作
dict.clear() 删除字典中所有元素
dict.copy() 返回字典(浅复制)的一个副本
dict.fromkeysc(seq,val=None)  创建并返回一个新字典,以seq 中的元素做该字典的键,val 做该字典中所有键对应的初始值(如果不提供此值,则默认为None)
dict.get(key,default=None)  对字典dict 中的键key,返回它对应的值value,如果字典中不存在此键,则返回default 的值(注意,参数default 的默认值为None)
dict.has_key(key) 如果键(key)在字典中存在,返回True,否则返回False. 在Python2.2版本引入in 和not in 后,此方法几乎已废弃不用了,但仍提供一个可工作的接口。
dict.items()  返回一个包含字典中(键, 值)对元组的列表
dict.keys() 返回一个包含字典中键的列表
dict.iter() 方法iteritems(), iterkeys(), itervalues()与它们对应的非迭代方法一样,不同的是它们返回一个迭代子,而不是一个列表。
dict.popc(key[, default]) 和方法get()相似,如果字典中key 键存在,删除并返回dict[key],如果key 键不存在,且没有给出default 的值,引发KeyError 异常。
dict.setdefault(key,default=None) 和方法set()相似,如果字典中不存在key 键,由dict[key]=default 为它赋值。
dict.update(dict2) 将字典dict2 的键-值对添加到字典dict
dict.values() 返回一个包含字典中所有值的列表

 

字典的键
字典中的值没有任何限制,可以是任意Python对象,但是字典中的键是有类型限制的。
1、不允许一个键对应多个对象,当有键冲突时,取最后的赋值。

>>> dict1 = {'a':123,'a':'abc'}
>>> dict1
{
'a': 'abc'}


2、键必须是可哈希的,像字典和列表这样的可变类型是不可哈希的,不能作为键。所有的不可变类型都是可哈希的,可以作为键。但是数值相等的数字哈希值相同,所以是相同的键。元组是不可变类型,但是它不是一成不变的,用元组做有效的键,元组中必须只包括像数字和字符串这样的不可变参数,才可以作为字典中有效的键。

>>> dict2 = {1:'abc', 1.0:'123'}
>>> dict2
{
1: '123'}
>>> dict3 = {(1,2,3):'123'}
>>> dict3
{(
1, 2, 3): '123'}
>>> dict4 = {([1,2,3],2):'123'}

Traceback (most recent call last):
File
"<pyshell#6>", line 1, in <module>
dict4
= {([1,2,3],2):'123'}
TypeError: unhashable type:
'list'

 

集合类型

数学上,把 set 称做由不同的元素组成的集合,集合(set)的成员通常被称做集合元素(set elements)。Python把这个概念引入到它的集合类型对象里。集合对象是一组无序排列的可哈希的值,所以可以做字典中的键。
和其他容器类型一样,集合可以用in和 not in操作符检查成员,由len()内建函数得到集合的基数(大小),用for循环迭代集合成员。但是因为集合本身无序,不可以为集合创建索引或执行切片操作,也没有键来获取集合中元素的值。
集合(sets)有两种类型,可变集合(set)和不可变集合(frozenset)。其中可变集合可以添加删除元素,但它是不可哈希的。不可变集合不可更改元素,但它可哈希。
Python的集合操作符是这样的

Python符号 说明
in  是...的成员
not in 不是...的成员
== 等于
!= 不等于
< 是...的(严格)子集
<= 是...的(非严格)子集
> 是...的(严格)超集
>= 是...的(非严格)超集
& 交集
| 并集
- 差补或相对补集
^ 对称差分



 
 
 
 
 
 

 
 

创建集合类型和给集合类型赋值
集合与列表([])和字典({})不同,没有特别的语法格式。列表和字典可以分别用他们自己的工厂方法list()和dict()创建,这是集合被创建的唯一方法——用集合的工厂方法 set() 和 frosenset():

>>> s = set('hellopython')
>>> s
set([
'e', 'h', 'l', 'o', 'n', 'p', 't', 'y'])
>>> t = frozenset(['a','b','c','d','e'])
>>> t
frozenset([
'a', 'c', 'b', 'e', 'd'])
>>> type(t)
<type 'frozenset'>
>>> type(s)
<type 'set'>
>>> len(s)
8

 

访问集合中的值

>>> 'e' in s
True
>>> 'a' in s
False
>>> for i in s:
print i

e
h
l
o
n
p
t
y

更新集合
如下操作:

>>> s.add('z')
>>> s
set([
'e', 'h', 'l', 'o', 'n', 'p', 't', 'y', 'z'])
>>> s.update('abc')
>>> s
set([
'a', 'c', 'b', 'e', 'h', 'l', 'o', 'n', 'p', 't', 'y', 'z'])
>>> s.remove('z')
>>> s
set([
'a', 'c', 'b', 'e', 'h', 'l', 'o', 'n', 'p', 't', 'y'])
>>> s -= set('python')
>>> s
set([
'a', 'c', 'b', 'e', 'l'])

 

集合类型操作符
如上表表示。
此处只写出一些运算符的使用方法:

>>> a = set('abcd')
>>> b = frozenset('cdef')
>>> a | b #
set(['a', 'c', 'b', 'e', 'd', 'f'])
>>> a & b #
set(['c', 'd'])
>>> a - b #
set(['a', 'b'])
>>> a ^ b #对称差分
set(['a', 'b', 'e', 'f'])
>>> b | a
frozenset([
'a', 'c', 'b', 'e', 'd', 'f'])
>>> b ^ a
frozenset([
'a', 'b', 'e', 'f'])

 

如果两个集合是不同类型的结合,那么结果类型和左操作数的类型相同

集合类型操作符(仅用于可变集合)
(Union) Update ( |= )
这个方法可以添加多个成员,和上面额update()等价

>>> a = set('abcd')
>>> a |= set('happy')
>>> a
set([
'a', 'c', 'b', 'd', 'h', 'p', 'y'])

 

保留/交集更新( &= )

>>> a = set('abdef')
>>> a &= set('abcd')
>>> a
set([
'a', 'b', 'd'])

 

差更新(-=)和对称差分更新)(^=)不赘述

集合类型内建方法

可用于全部集合的方法 操作
s.issubset(t) 如果s 是t 的子集,则返回True,否则返回False
s.issuperset(t) 如果t 是s 的超集,则返回True,否则返回False
s.union(t) 返回一个新集合,该集合是s 和t 的并集
s.intersection(t) 返回一个新集合,该集合是s 和t 的交集
s.difference(t)  返回一个新集合,该集合是s 的成员,但不是t 的成员
s.symmetric_difference(t) 返回一个新集合,该集合是s 或t 的成员,但不是s 和t 共有的成员
s.copy() 返回一个新集合,它是集合s 的浅复制

 

可变集合类型的方法 操作
s.update(t) 用t 中的元素修改s, 即,s 现在包含s 或t 的成员
s.intersection_update(t)  s 中的成员是共同属于s 和t 的元素
s.difference_update(t)  s 中的成员是属于s 但不包含在t 中的元素
s.symmetric_difference_update(t)  s中的成员更新为那些包含在s 或t 中,但不 是s和t 共有的元素
s.add(obj) 在集合s 中添加对象obj
s.remove(obj)  从集合s 中删除对象obj;如果obj 不是集合s 中的元素(obj not in s),将引发KeyError 错误
s.discard(obj)  如果obj 是集合s 中的元素,从集合s 中删除对象obj
s.pop() 删除集合s 中的任意一个对象,并返回它
s.clear()  删除集合s 中的所有元素