0.说明
依然是按照前面介绍的几种序列类型的思路来总结字映像类型和集合类型,即先做一个介绍,再讨论可用操作符、工厂函数、内建函数和方法。
1.映射类型:字典
映射类型被称做哈希表,而Python中的字典对象就是哈希类型,即它是按照这样的方式来存储数据:(哈希表的算法)是获取键,对键执行一个叫做哈希函数的操作,并根据计算的结果,选择在数据结构的某个地址中来存储对象的值。任何一个值存储的地址取决于它的键,正因为这种随意性,哈希表中的值是没有顺序的,所以Python中的字典对象中的元素也是无序的。
下面是字典的基本操作:
(1)创建字典和给字典赋值
主要的方法如下:
- 直接创建赋值:可整体赋值,也可以逐一添加键值对
- 工厂函数dict()
1
2
3
|
>>> fdict = dict (([ 'xpleaf' , 'boy' ], [ 'cl' , 'girl' ]))
>>> fdict
{ 'xpleaf' : 'boy' , 'cl' : 'girl' }
|
- 内建函数fromkeys():创建默认字典,字典中元素具有相同的值(如果没有给出,默认为None)
1
2
3
4
5
6
|
>>> fdict = {}.fromkeys(( 'xpleaf' , 'cl' ), 'lovings' )
>>> fdict
{ 'xpleaf' : 'lovings' , 'cl' : 'lovings' }
>>> edict = {}.fromkeys(( 'xpleaf' , 'cl' ))
>>> edict
{ 'xpleaf' : None , 'cl' : None }
|
(2)访问字典中的值
1
2
3
4
5
6
|
>>> fdict = { 'xpleaf' : 'boy' , 'cl' : 'girl' }
>>> for key in fdict.keys():
... print key, fdict[key]
...
xpleaf boy
cl girl
|
1
2
3
4
5
6
|
>>> fdict = { 'xpleaf' : 'boy' , 'cl' : 'girl' }
>>> for key in fdict:
... print key, fdict[key]
...
xpleaf boy
cl girl
|
1
2
3
4
5
6
7
|
>>> fdict = { 'xpleaf' : 'boy' , 'cl' : 'girl' }
>>> fdict.has_key( 'xpleaf' )
True
>>> 'xpleaf' in fdict
True
>>> 'clyyh' in fdict
False
|
(3)更新字典
可以更新已有的键值对或添加新的键值对:
1
2
3
4
5
|
>>> fdict = { 'host' : 'xpleaf' , 'port' : 80 }
>>> fdict[ 'port' ] = 3389
>>> fdict[ 'ip' ] = '121.42.147.131'
>>> print 'host: %(host)s, port: %(port)s, ip: %(ip)s' % fdict
host: xpleaf, port: 3389 , ip: 121.42 . 147.131
|
(4)删除字典元素和字典
1
2
3
4
|
>>> fdict = { 'host' : 'xpleaf' , 'port' : 80 , 'ip' : '121.42.147.131' }
>>> del fdict[ 'port' ] #删除一个键值对
>>> fdict.clear() #删除字典中所有的键值对
>>> del fdict #删除整个字典
|
2.映射类型操作符
除了不支持拼接和重复,字典可以和所有的标准类型操作符一起工作。
(1)标准类型操作符
在《Python回顾与整理2:Python对象》中已经有介绍过标准类型操作符,它们对字典类型也是适合的,主要是:>、<、==和and等,如下:
1
2
3
4
5
6
|
>>> dict1 = { 'abc' : 123 }
>>> dict2 = { 'abc' : 456 }
>>> dict1 < dict2
True
>>> dict1 = = dict2
False
|
(2)映射类型操作符
对序列类型来说,用索引做唯一参数或下标以获取一个序列的值,但是对字典来说,是用键查询,键是参数,而不是索引。通过`[]`操作符,可以在字典中查找元素,也可以为某个元素赋值。
当然也可以用has_key()。
3.映射类型的内建函数和工厂函数
(1)标准类型函数type()、str()、cmp()
这里不介绍cmp(),因为字典的比较算法比较复杂,而且不是很经常用,其它两个如下:
1
2
3
4
5
6
7
|
>>> d = { 'name' : 'xpleaf' , 'age' : 21 }
>>> str (d)
"{'age': 21, 'name': 'xpleaf'}"
>>> unicode (d)
u "{'age': 21, 'name': 'xpleaf'}"
>>> type (d)
< type 'dict' >
|
(2)映射类型相关的函数
如果参数是容器类型并且是可迭代的,那么可抚今追昔的元素必须成对出现,从而生成一个字典:
1
2
3
4
5
6
7
8
|
>>> dict ( zip (( 'x' , 'y' ), ( 1 , 2 )))
{ 'y' : 2 , 'x' : 1 }
>>> dict ([[ 'x' , 1 ], [ 'y' , 2 ]])
{ 'y' : 2 , 'x' : 1 }
>>> [( 'xy' [i - 1 ], i) for i in range ( 1 , 3 )]
[( 'x' , 1 ), ( 'y' , 2 )]
>>> dict ([( 'xy' [i - 1 ], i) for i in range ( 1 , 3 )])
{ 'y' : 2 , 'x' : 1 }
|
如果参数也是一个映射类型,比如一个字典对象,则会生成一个浅拷贝,但建议使用copy()方法:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
>>> d = { 'name' : 'xpleaf' , 'age' : 21 }
>>> d2 = dict (d)
>>> d2
{ 'age' : 21 , 'name' : 'xpleaf' }
>>> id (d), id (d2)
( 139762050623200 , 139762085625480 )
>>> [( id (x), id (d[x])) for x in d]
[( 139762085618632 , 23490424 ), ( 139762086747760 , 139762085603104 )]
>>> [( id (x), id (d[x])) for x in d2]
[( 139762085618632 , 23490424 ), ( 139762086747760 , 139762085603104 )]
>>>
>>> d3 = d2.copy()
>>> d3
{ 'age' : 21 , 'name' : 'xpleaf' }
|
当然dict()还可以接受关键字参数:
1
2
|
>>> dict (x = 1 , y = 2 )
{ 'y' : 2 , 'x' : 1 }
|
1
2
3
|
>>> d = { 'name' : 'xpleaf' , 'age' : 21 }
>>> len (d)
2
|
- hash():不是为字典设计的方法,但是可以判断某个对象是否可以作为一个字典的键
1
2
3
4
5
6
|
>>> hash ( 'xpleaf' )
- 166083108737309362
>>> hash ([])
Traceback (most recent call last):
File "<stdin>" , line 1 , in <module>
TypeError: unhashable type : 'list'
|
另外,即使那个对象的数据类型不同,但只要它们的值相同,所得哈希值也是一样的:
1
2
3
4
|
>>> hash ( 'xpleaf' )
- 166083108737309362
>>> hash (u 'xpleaf' )
- 166083108737309362
|
4.映射类型内建方法
常见的内建方法如下:
1
2
3
4
5
6
|
>>> d = { 'name' : 'xpleaf' , 'age' : 21 , 'loving' : 'cl' }
>>> d
{ 'age' : 21 , 'name' : 'xpleaf' , 'loving' : 'cl' }
>>> d.clear()
>>> d
{}
|
- dict.copy():返回字典的一个浅拷贝
- dict.fromkeys(seq, val=None):创建并返回一个字典,以seq中的元素做该字典的键,val做该字典中所有键对的初始值(如果不提供些值,则默认为None)
1
2
3
4
|
>>> {}.fromkeys(( 'name' , 'age' , 'loving' ), 'Not set' )
{ 'age' : 'Not set' , 'name' : 'Not set' , 'loving' : 'Not set' }
>>> {}.fromkeys(( 'name' , 'age' , 'loving' ))
{ 'age' : None , 'name' : None , 'loving' : None }
|
- dict.get(key, default=None):返回字典中key对应的value,如果字典中不存在此键,则返回default的值(参数default的默认值为None)
1
2
3
4
5
6
|
>>> d = { 'name' : 'xpleaf' , 'age' : 21 , 'loving' : 'cl' }
>>> d.get( 'name' )
'xpleaf'
>>> d.get( 'clyyh' )
>>> d.get( 'clyyh' , 'Not found' )
'Not found'
|
- dict.has_keys():判断键是否存在于字典中,但现在建议用成员操作符in和not in
- dict.items():返回一个包含字典中、键值对元组的列表
1
2
3
4
5
|
>>> d = { 'name' : 'xpleaf' , 'age' : 21 , 'loving' : 'cl' }
>>> d.items()
[( 'age' , 21 ), ( 'name' , 'xpleaf' ), ( 'loving' , 'cl' )]
>>> sorted (d.items()) #排序输出
[( 'age' , 21 ), ( 'loving' , 'cl' ), ( 'name' , 'xpleaf' )]
|
- dict.keys():返回一个包含字典中键的列表
1
2
3
4
5
6
7
8
9
10
11
|
>>> d = { 'name' : 'xpleaf' , 'age' : 21 , 'loving' : 'cl' }
>>> d.keys()
[ 'age' , 'name' , 'loving' ]
>>> sorted (d.keys()) #排序输出
[ 'age' , 'loving' , 'name' ]
>>> sort_keys = d.keys()
>>> sort_keys
[ 'age' , 'name' , 'loving' ]
>>> sort_keys.sort() #调用列表的sort()方法
>>> sort_keys
[ 'age' , 'loving' , 'name' ]
|
- dict.values():返回一个包含字典中所有值的列表
1
2
3
|
>>> d = { 'name' : 'xpleaf' , 'age' : 21 , 'loving' : 'cl' }
>>> d.values()
[ 21 , 'xpleaf' , 'cl' ]
|
- dict.iter*():方法iteritems()、iterkeys()、itervalues()与它们对应的非迭代方法一样,不同的是它们返回一个迭代子,而不是一个列表
1
2
3
4
5
6
7
8
9
10
11
12
|
>>> d = { 'name' : 'xpleaf' , 'age' : 21 , 'loving' : 'cl' }
>>> iter_keys = d.iterkeys()
>>> iter_keys
<dictionary - keyiterator object at 0x7f1ce39a25d0 >
>>> type (iter_keys)
< type 'dictionary-keyiterator' >
>>> for key in iter_keys:
... print key
...
age
name
loving
|
当字典非常大时,使用这三种方法就可以大大节省内存空间,因为这三种方法的非迭代子方法返回的数据是直接存储在内存当中的,而这三种方法返回的是一个迭代子,可以理解为一个函数,用于动态获取字典中的这些值。
- dict.pop(key[, default]):和get()方法类似,如果字典中key键存在,删除并返回dict[key];如果key键不存在,且没有给出default的值,则引发KeyError异常(这点与get()方法不同)
1
2
3
4
5
6
7
8
9
10
11
|
>>> d = { 'name' : 'xpleaf' , 'age' : 21 , 'loving' : 'cl' }
>>> d.pop( 'loving' )
'cl'
>>> d
{ 'age' : 21 , 'name' : 'xpleaf' }
>>> d.pop( 'clyyh' , 'Not found' )
'Not found'
>>> d.pop( 'clyyh' )
Traceback (most recent call last):
File "<stdin>" , line 1 , in <module>
KeyError: 'clyyh'
|
- dict.popitem():随机删除一对键值对并以元组的形式返回
1
2
3
|
>>> d = { 'name' : 'xpleaf' , 'age' : 21 , 'loving' : 'cl' }
>>> d.popitem()
( 'age' , 21 )
|
- dict.setdefault(key, default=None):检查字典中是否含有某键,如果这个键存在,则返回该键对应的值;如果不存在,则可以给这个键赋默认值并返回此值
1
2
3
4
5
6
7
8
9
10
|
>>> d = { 'name' : 'xpleaf' , 'age' : 21 , 'loving' : 'cl' }
>>> d.setdefault( 'name' )
'xpleaf'
>>> d.setdefault( 'clyyh' )
>>> d
{ 'age' : 21 , 'clyyh' : None , 'name' : 'xpleaf' , 'loving' : 'cl' }
>>> d.setdefault( 'love' , 'Not set' )
'Not set'
>>> d
{ 'love' : 'Not set' , 'age' : 21 , 'clyyh' : None , 'name' : 'xpleaf' , 'loving' : 'cl' }
|
- dict.update(dict2):将字典dict2的键值对添加到dict中,字典中原有的键如果与新添加的键重复,那么原来字典中该键所对应的值就会被更新覆盖
1
2
3
4
5
|
>>> d = { 'name' : 'xpleaf' , 'age' : 21 , 'loving' : 'cl' }
>>> d2 = { 'name' : 'yonghaoye' , 'clyyh' : 'forever' }
>>> d.update(d2)
>>> d
{ 'age' : 21 , 'clyyh' : 'forever' , 'name' : 'yonghaoye' , 'loving' : 'cl' }
|
5.字典的键
字典中的值是没有任何限制的,可以是任意Python对象,但是字典中的键是有限制的。
(1)不允许一个键对应多个值
从字典的存储方式去理解,这也是很合理的,因为值的存储地址就是通过字典的键来生成的。当有键发生冲突(即字典键重复赋值)时,会取最后(最近)的赋值,而不会产生错误,这是因为如果对每一个键值对赋值时都检查该键是否存在,会占用一定的内存,相比之下,直接把该键原来对应的值覆盖的性能会更好。
1
2
3
4
5
6
|
>>> d = { 'name' : 'xpleaf' , 'name' : 'clyyh' }
>>> d
{ 'name' : 'clyyh' }
>>> d[ 'name' ] = 'xpleaf'
>>> d
{ 'name' : 'xpleaf' }
|
(2)键必须是可哈希的
1
2
3
|
>>> d = {u 'name' : 'xpleaf' , 'name' : 'xpleaf' , 1 : 'clyyh' , 1.0 : 'clyyh' }
>>> d
{ 1 : 'clyyh' , u 'name' : 'xpleaf' }
|
- 有一些可变对象是可哈希的,如定义了__hash__()特殊方法的类
因为__hash__()方法返回一个整型,所以仍然是用不可变的值来做字典的键。
解释器调用哈希函数,根据字典中的值来计算存储数据的位置。如果键是可变对象,那么它的值可改变。当键发生变化时,哈希函数会映像到不同的地址来存储数据。如果这样的情况发生,哈希函数就不可能可靠地存储或获取相关的数据。选择可哈希的键的原因就是因为它们的值不能改变。
6.集合类型
在数学上,集合由不同的元素组成,Python把这个概念引入到集合类型对象中。
在Python集合中,集合对象的成员(集合元素)是一组无序排列的可哈希的值,这也意味着集合的元素是不可变对象,因此都可以作为字典的键。而Python中的集合又可以分为两种:
- 可变集合set:可以添加和删除元素,是一个不可哈希的集合对象,因此不可以作为字典中的键或其他集合中的元素
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
>>> set_a = set ( 'xpleaf' )
>>> set_a
set ([ 'a' , 'e' , 'f' , 'l' , 'p' , 'x' ]) #无序排列
>>> hash (set_a) #不可哈希
Traceback (most recent call last):
File "<stdin>" , line 1 , in <module>
TypeError: unhashable type : 'set'
>>> set_a.add( 'clyyh' ) #添加元素
>>> set_a
set ([ 'a' , 'e' , 'f' , 'l' , 'p' , 'x' , 'clyyh' ])
>>> set_a.remove( 'clyyh' ) #删除元素
>>> set_a
set ([ 'a' , 'e' , 'f' , 'l' , 'p' , 'x' ])
>>> set_a.add( set ( 'clyyh' )) #set集合本身不可以作为集合中的元素,因为集合中的元素必须是可哈希的
Traceback (most recent call last):
File "<stdin>" , line 1 , in <module>
TypeError: unhashable type : 'set'
|
- 不可变集合frozenset:不可以添加和删除元素,是一个可哈希的集合对象,因此可以作为字典中的键或是作为集合中的一个成员
1
2
3
4
5
6
7
8
9
10
|
>>> frozenset_b = frozenset ( 'xpleaf' )
>>> frozenset_b
frozenset ([ 'a' , 'e' , 'f' , 'l' , 'p' , 'x' ])
>>> hash (frozenset_b)
6226730480975949720
>>> dir (frozenset_b) #没有添加和删除元素的方法
[ '__and__' , '__class__' , '__cmp__' , '__contains__' , '__delattr__' , '__doc__' , '__eq__' , '__format__' , '__ge__' , '__getattribute__' , '__gt__' , '__hash__' , '__init__' , '__iter__' , '__le__' , '__len__' , '__lt__' , '__ne__' , '__new__' , '__or__' , '__rand__' , '__reduce__' , '__reduce_ex__' , '__repr__' , '__ror__' , '__rsub__' , '__rxor__' , '__setattr__' , '__sizeof__' , '__str__' , '__sub__' , '__subclasshook__' , '__xor__' , 'copy' , 'difference' , 'intersection' , 'isdisjoint' , 'issubset' , 'issuperset' , 'symmetric_difference' , 'union' ]
>>> set_a.add(frozenset_b) #frozenset集合可以作为集合中的元素
>>> set_a
set ([ 'a' , 'e' , 'f' , 'l' , 'p' , frozenset ([ 'a' , 'e' , 'f' , 'l' , 'p' , 'x' ]), 'x' ])
|
但需要注意的是,因为集合本身是无序的,不可以为集合创建索引或执行切片操作,也没有键可用来获取集合中的元素:
1
2
3
4
5
6
7
8
9
10
11
|
>>> set_a = set ( 'xpleaf' )
>>> set_a
set ([ 'a' , 'e' , 'f' , 'l' , 'p' , 'x' ])
>>> set_a[ 0 ]
Traceback (most recent call last):
File "<stdin>" , line 1 , in <module>
TypeError: 'set' object does not support indexing
>>> set_a[ 'a' ]
Traceback (most recent call last):
File "<stdin>" , line 1 , in <module>
TypeError: 'set' object has no attribute '__getitem__'
|
下面是数学集合操作符与Python集合操作符的对比说明:
集合操作符和关系符号 |
数学符号 |
Python符号 |
说明 |
∈ |
in |
是……的成员 |
|
not in |
不是……的成员 |
= |
== |
等于 |
≠ |
!= |
不等于 |
|
< |
是……的真子集 |
|
<= |
是……的子集 |
|
> |
是……的真超集 |
|
>= |
是……的超集 |
∩
|
& |
交集 |
∪ |
| |
并集 |
-或\ |
- |
差集或相对补集 |
Δ |
^ |
对称差分 |
下面是集合的基本操作:
与列表和字典不同,集合只能通过工厂函数set()或frozenset()来创建:
1
2
3
4
5
6
|
>>> a = set ( 'xpleaf' )
>>> b = frozenset ( 'xpleaf' )
>>> type (a)
< type 'set' >
>>> type (b)
< type 'frozenset' >
|
可以通过遍历或检查某项元素中否是一个集合的成员来实现:
1
2
3
4
5
6
7
|
>>> s = set ( 'xpleaf' )
>>> 'x' in s
True
>>> for i in s:
... print i,
...
a e f l p x
|
对于可变集合set,可以使用集合的内建方法add()、remove()、update()和操作符`-`等来更新集合:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
>>> s = set ( 'xpleaf' )
>>> s
set ([ 'a' , 'e' , 'f' , 'l' , 'p' , 'x' ])
>>> s.add( 'clyyh' )
>>> s
set ([ 'a' , 'e' , 'f' , 'l' , 'p' , 'x' , 'clyyh' ])
>>>
>>> s.remove( 'clyyh' )
>>> s
set ([ 'a' , 'e' , 'f' , 'l' , 'p' , 'x' ])
>>>
>>> s.update( 'cl' ) #注意update()是先将'cl'变为一个集合再合并到原来集合中,这与add()方法不同
>>> s
set ([ 'a' , 'c' , 'e' , 'f' , 'l' , 'p' , 'x' ])
>>>
>>> s - = set ( 'xpleaf' )
>>> s
set ([ 'c' ])
|
删除集合中的成员只针对于可变集合,上面已有提及,而对于集合本身,可以直接使用del来删除。
7.集合类型操作符
(1)标准类型操作符(适用于所有集合类型)
1
2
3
4
5
|
>>> s = set ( 'xpleaf' )
>>> 'x' in s
True
>>> 'c' in s
False
|
可以认为是数学中的集合相等与不相等,两种集合之间也可以比较:
1
2
3
4
5
6
|
>>> set ( 'xpleaf' ) = = frozenset ( 'xpleaf' )
True
>>> set ( 'xpleaf' ) = = frozenset ( 'leaf' )
False
>>> set ( 'xpleaf' ) ! = frozenset ( 'leaf' )
True
|
直接从元素是否相互包含的角度去理解即可:
1
2
3
4
5
6
|
>>> set ( 'xpleaf' ) > frozenset ( 'leaf' )
True
>>> set ( 'xpleaf' ) > frozenset ( 'xpleaf' )
False
>>> set ( 'xpleaf' ) > = frozenset ( 'xpleaf' )
True
|
(2)集合类型操作符(适用于所有的集合类型)
1
2
3
4
|
>>> s = set ( 'xpleaf' )
>>> t = frozenset ( 'leafhao' )
>>> s | t
set ([ 'a' , 'e' , 'f' , 'h' , 'l' , 'o' , 'p' , 'x' ])
|
当然也可以使用集合的内建方法union():
1
2
3
4
|
>>> s.union(t)
set ([ 'a' , 'e' , 'f' , 'h' , 'l' , 'o' , 'p' , 'x' ])
>>> t.union(s)
frozenset ([ 'a' , 'e' , 'f' , 'h' , 'l' , 'o' , 'p' , 'x' ])
|
1
2
3
4
|
>>> s = set ( 'xpleaf' )
>>> t = frozenset ( 'leafhao' )
>>> s & t
set ([ 'a' , 'e' , 'l' , 'f' ])
|
除了使用`&`操作符,也可以使用集合的内建方法intersection():
1
2
|
>>> s.intersection(t)
set ([ 'a' , 'e' , 'l' , 'f' ])
|
1
2
3
4
5
6
|
>>> s = set ( 'xpleaf' )
>>> t = frozenset ( 'leafhao' )
>>> s - t
set ([ 'p' , 'x' ])
>>> t - s
frozenset ([ 'h' , 'o' ])
|
除了使用`-`操作符,也可以使用集合的内建方法difference():
1
2
3
4
|
>>> s.difference(t)
set ([ 'p' , 'x' ])
>>> t.difference(s)
frozenset ([ 'h' , 'o' ])
|
两个集合(s和t)的对称差分是指另外一个集合C,该集合中的元素只能是属于集合s或者集合t的成员,不能同时属于两个集合(类似于异或):
1
2
3
4
|
>>> s = set ( 'xpleaf' )
>>> t = frozenset ( 'leafhao' )
>>> s ^ t
set ([ 'p' , 'x' , 'h' , 'o' ])
|
除了使用`-`操作符,也可以使用集合的内建方法symmetric_dirrerence():
1
2
|
>>> s.symmetric_difference(t)
set ([ 'p' , 'x' , 'h' , 'o' ])
|
在上面的演示中,左边的s是可变集合,而右边的t是一个不可变集合,而所得的结果是可变集合,但如果把两个操作数的顺序反过来,结果就不一样了:
1
2
3
4
5
6
|
>>> t | s
frozenset ([ 'a' , 'e' , 'f' , 'h' , 'l' , 'o' , 'p' , 'x' ])
>>> t ^ s
frozenset ([ 'p' , 'h' , 'x' , 'o' ])
>>> t - s
frozenset ([ 'h' , 'o' ])
|
即如果左右两个操作数的类型相同,则所产生的结果类型是相同的;如果不相同,则结果与左操作数的类型相同。但需要注意的是,加号`+`并不是集合类型的操作符:
1
2
3
4
|
>>> s + set ( 'leaf' )
Traceback (most recent call last):
File "<stdin>" , line 1 , in <module>
TypeError: unsupported operand type (s) for + : 'set' and 'set'
|
(3)集合类型操作符(仅适用于可变集合)
其实就上面的四种操作符,只不过将其作为方法加进可变集合中或通过操作符实现,从而直接对可变集合本身产生影响:
1
2
3
4
5
6
7
|
>>> s = set ( 'xpleaf' )
>>> s2 = set ( 'leafhao' )
>>> s
set ([ 'a' , 'e' , 'f' , 'l' , 'p' , 'x' ])
>>> s | = s2
>>> s
set ([ 'a' , 'e' , 'f' , 'h' , 'l' , 'o' , 'p' , 'x' ])
|
- 保留更新(&=或intersection_update())
1
2
3
4
5
6
7
|
>>> s = set ( 'xpleaf' )
>>> s2 = set ( 'leafhao' )
>>> s
set ([ 'a' , 'e' , 'f' , 'l' , 'p' , 'x' ])
>>> s & = s2
>>> s
set ([ 'a' , 'e' , 'l' , 'f' ])
|
- 差集更新(-=或difference_update())
1
2
3
4
5
6
7
|
>>> s = set ( 'xpleaf' )
>>> s2 = set ( 'leafhao' )
>>> s
set ([ 'a' , 'e' , 'f' , 'l' , 'p' , 'x' ])
>>> s - = s2
>>> s
set ([ 'p' , 'x' ])
|
- 对称差分更新(^=或symmetric_diffenence_update())
1
2
3
4
5
6
7
|
>>> s = set ( 'xpleaf' )
>>> s2 = set ( 'leafhao' )
>>> s
set ([ 'a' , 'e' , 'f' , 'l' , 'p' , 'x' ])
>>> s ^ = s2
>>> s
set ([ 'h' , 'o' , 'p' , 'x' ])
|
8.内建函数
(1)标准类型函数
1
2
3
4
5
6
|
>>> s = set ( 'xpleaf' )
>>> t = frozenset ( 'clyyh' )
>>> len (s)
6
>>> len (t)
4
|
(2)集合类型工厂函数
主要是set()和frozenset(),分别用来生成可变和不可变集合,主要有下面两种方式:
1
2
3
4
|
>>> set ()
set ([])
>>> frozenset ()
frozenset ([])
|
- 提供参数:如果提供参数,则该参数必须是可迭代的,即一个序列,或迭代器,或支持迭代的一个对象,例如一个文件或一个字典
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
>>> set ([ 'xpleaf' , 'clyyh' ])
set ([ 'clyyh' , 'xpleaf' ])
>>>
>>> frozenset ({ 'name' : 'xpleaf' , 'age' : 21 })
frozenset ([ 'age' , 'name' ])
>>>
>>> f = open ( 'numbers' , 'w' )
>>> for i in range ( 5 ):
... f.write( '%d\n' % i)
...
>>> f.close()
>>> f = open ( 'numbers' , 'r' )
>>> set (f)
set ([ '0\n' , '3\n' , '1\n' , '4\n' , '2\n' ])
>>> f.close()
|
9.集合类型内建方法
(1)适用于所有集合类型的方法
如下:
方法名称 |
操作 |
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的浅复制 |
需要注意的是,内建方法copy()没有等价的操作符,和同名的字典内建方法dict.copy()一样,copy()方法比用像set()、frozenset()或dict()这样的工厂方法提制对象的副本要快,测试程序如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
#!/usr/bin/env python
from time import time
def get_set_time():
start_time = time()
s = set ( 'xpleaf' )
end_time = time()
return end_time - start_time
def get_copy_time():
s = set ( 'xpleaf' )
start_time = time()
s2 = s.copy()
end_time = time()
return end_time - start_time
def get_result():
s_longer_than_c = 0
times = 100
for i in range (times):
if get_set_time() > get_copy_time():
s_longer_than_c + = 1
if s_longer_than_c ! = 0 :
return s_longer_than_c / float (times)
if __name__ = = '__main__' :
rate = get_result()
print 'Result***'
print 'The rate that set_method_time is longer than copy_method_time is:' , rate
|
执行如下:
1
2
3
|
/usr/bin/python2 .7 /home/xpleaf/PycharmProjects/Python_book/7/test_time .py
Result***
The rate that set_method_time is longer than copy_method_time is: 0.51
|
当然,并不总是如此的,有时候会小于0.5,并且可能性也不小,这里只是作为简单的测试而已,实际上在使用时不用纠结太多。
(2)只适用于可变集合的方法
如下:
方法名称 |
操作 |
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() |
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是集合s中的元素,从集合s中删除对象obj |
s.pop() |
删除集合s中的任意一个对象,并返回它 |
s.clear() |
删除集合s中的所有元素
|
有了前面的基础之后,这些方法都比较简单,所以这里就不给出例子了,不过需要注意的是,需要接受参数的方法,其参数必须是可哈希的。
(3)操作符和内建方法比较
像上面看到的那样,很多内建的方法几乎和操作符等价。之所以说几乎等价而不是完全等价,是因为:当用操作符时,操作符两边的操作数必须是集合,而在使用内建方法时,对象也可以是迭代类型的。原因:采用易懂的set('abc').intersection('cbs')可以避免使用set('abc') `操作符` 'cbs'这样容易出错的构建方法。可以看下面的一个例子:
1
2
3
4
5
6
7
8
9
|
>>> s = set ( 'xpleaf' )
>>> s.intersection( 'leaf' )
set ([ 'a' , 'e' , 'l' , 'f' ])
>>> s & set ( 'leaf' )
set ([ 'a' , 'e' , 'l' , 'f' ])
>>> s & 'leaf'
Traceback (most recent call last):
File "<stdin>" , line 1 , in <module>
TypeError: unsupported operand type (s) for &: 'set' and 'str'
|
10.集合类型总结表
可以参考书上的总结表,非常详细。
11.相关模块
可以不用考虑,直接使用映射和集合类型即可。
时间: 2024-12-27 07:29:00