Python编程系列2-字典、元组与集合

  • 字典
  • 元组
  • 集合

1.7 字典(dictionary)

  • 字典在某些语言中可能称为 联合内存 (associative memories) 或 联合数组 (associative arrays)。序列是以连续的整数为索引,与此不同的是,字典以”关键字”为索引,关键字可以是任意不可变类型,通常用字符串或数值。如果元组中只包含字符串和数字,它可以作为关键字,如果它直接或间接地包含了可变对象,就不能当做关键字。不能用列表做关键字,因为列表可以用索引、切割或者 append() 和 extend() 等方法改变。
  • 字典是无序的键:值对 (key:value 对)集合,键必须是互不相同的(在同一个字典之内)。使用大括号创建一个空的字典:{}。初始化列表时,在大括号内放置一组逗号分隔的键:值对,这也是字典输出的方式。
  • 字典的主要操作是依据键来存储和取值。也可以用 del 来删除{键:值}对(key:value),从一个不存在的键中取值会导致错误。
In [1]:
# 通过键值提取数据
d = {'rice':35, 'wheat':101, 'corn':67}
print(d)
print(d['rice'])
Out[1]:
{'rice': 35, 'corn': 67, 'wheat': 101}
35
In [2]:
# 把数据放入dict还可以直接通过key放入
d['egg'] = 33
d
Out[2]:
{'corn': 67, 'egg': 33, 'rice': 35, 'wheat': 101}
In [3]:
# 一个key只能对应一个value,多次对一个key放入value,后面的值会把前面的值冲掉
d['corn'] = 88
d
Out[3]:
{'corn': 88, 'egg': 33, 'rice': 35, 'wheat': 101}
In [4]:
# 如果key不存在,dict就会报错。要避免key不存在的错误,有两种办法,一是通过 in 判断key是否存在,二是通过dict提供的 get 方法,

d['meat']
Out[4]:
--------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
<ipython-input-4-ea5d78ac8eda> in <module>()
      1 # 如果key不存在,dict就会报错。要避免key不存在的错误,有两种办法,一是通过 in 判断key是否存在,二是通过dict提供的 get 方法,
      2 
----> 3 d['meat']

KeyError: 'meat'
In [5]:
'meat' in d
Out[5]:
False
In [6]:
# 如果key不存在,可以返回None(返回None的时候Python的交互式命令行不显示结果),或者自己指定的value

d.get('meat')
In [7]:
d.get('meat',45)
Out[7]:
45
In [8]:
# 删除一个key,使用pop(key)方法,对应的value也会从dict中删除
d.pop('rice')
d
Out[8]:
{'corn': 88, 'egg': 33, 'wheat': 101}

使用dict有下面几点需要注意

  1. dict内部存放的顺序和key放入的顺序是没有关系的
  2. dict查找和插入的速度极快,不会随着key的增加而增加,但是需要占用大量的内存,内存浪费多
  3. dict的key必须是**不可变对象**。字符串、整数等都是不可变的,可以放心地作为key,而list是可变的,就不能作为key
In [9]:
k = [3,4,5]
d[k] = 6
Out[9]:
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-9-4f152d4db5f4> in <module>()
      1 k = [3,4,5]
----> 2 d[k] = 6

TypeError: unhashable type: 'list'

常见字典操作方法

  • D.clear() 删除字典内所有元素
  • D.copy() 返回一个字典的复制
  • D.fromkeys(seq,val) 创建一个新字典,以序列seq中元素做字典的键,val为字典所有键对应的初始值
  • D.get(key, default=None) 返回指定键的值,如果值不在字典中返回default值
  • D.has_key(key) 如果键在字典dict里返回true,否则返回false
  • D.items() 以列表返回可遍历的(键, 值) 元组数组
  • D.keys() 以列表返回一个字典所有的键
  • D.setdefault(key, default=None) 和get()类似, 但如果键不存在于字典中,将会添加键并将值设为default
  • D.update(dict2) 把字典dict2的键/值对更新到dict里
  • D.values() 以列表返回字典中的所有值
  • D.pop(key) 删除一个键并返回它的值,类似于列表的pop,只不过删除的是一个键不是一个可选的位置
  • del D[key] 删除键
  • D[key] = 42 新增或修改键

字典用法注意事项

  1. 序列运算无效,字典元素间是没有顺序的概念
  2. 对新索引赋值会添加项
  3. 键不一定总是字符串

多种构造字典方式

  • dict() 构造函数可以直接从 key-value 对中创建字典
  • 如果关键字都是简单的字符串,有时通过关键字参数指定 key-value 对更为方便
  • 字典推导式可以从任意的键值表达式中创建字典
In [10]:
# 键值对构建字典
dict([('apple', 4139), ('peach', 4127), ('cherry', 4098)])
Out[10]:
{'apple': 4139, 'cherry': 4098, 'peach': 4127}
In [11]:
# 创建一个新字典,以序列seq中元素做字典的键,val为字典所有键对应的初始值
dict.fromkeys(['a','b'], 1) 
Out[11]:
{'a': 1, 'b': 1}
In [12]:
dict(zip(['a','b','c'],[1,2,3]))
Out[12]:
{'a': 1, 'b': 2, 'c': 3}
In [13]:
{k:v for (k,v) in zip(['a','b','c'],[1,2,3])}
Out[13]:
{'a': 1, 'b': 2, 'c': 3}
In [14]:
# 字典推导式
{x: x**2 for x in (2, 4, 6)}
Out[14]:
{2: 4, 4: 16, 6: 36}
In [15]:
# 关键字参数指定
D = dict(a=1,b=2,c=3)
D 
Out[15]:
{'a': 1, 'b': 2, 'c': 3}

1.8 元组

元组(tuple)是另一种有序的数据类型,与list比较类似。主要不同的一点是tuple被创建后就不能对其进行修改。所以,tuple与list不同,没有append(),pop(),insert()这些方法可以使用。获取元素的方法和list是一样的,可以通过索引来访问(也是从0开始的),只不过不能赋值成为其他的元素。

因为tuple不可变,所以代码更安全。如果可以的话,我们尽量使用tuple代替list。

In [16]:
# 定义一个空的tuple
t = ()
t
Out[16]:
()
In [17]:
# 只有1个元素的元组在进行定义的时候,需要加一个逗号 , 来消除歧义,否则定义的就不是一个元组而是元素本身
t1 = (3)
t2 = (3, )
print(t1)
print(t2)
Out[17]:
3
(3,)

1.8.1 元组的连接

如前面所说,元组是不可改的,但是可以连接

可以使用 + 对元组进行连接,例如

In [18]:
t1 = (2,3,5)
t2 = ('ricequant','python')
t3 = t1 + t2
t3
Out[18]:
(2, 3, 5, 'ricequant', 'python')

1.8.2 元组的删除

元组中的元素不能被删除,但是我们可以使用 del 删除整个元组,删除后可以重新定义

In [19]:
t4 = ('a',2,'b')
t4
Out[19]:
('a', 2, 'b')
In [20]:
del t4
t4
Out[20]:
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
<ipython-input-20-e94d0dfc4c8d> in <module>()
      1 del t4
----> 2 t4

NameError: name 't4' is not defined

事实上,上面所说的元素不变是指每个元素的指向永远不变。即指向1,就不能改成指向2,指向一个list,就不能改成指向其他对象,但指向的这个list本身是可变的,例如:

In [21]:
tup = (1,2,[3,4,5])
tup
Out[21]:
(1, 2, [3, 4, 5])
In [22]:
tup[2][0] = 7
tup[2][1] = 11
tup
Out[22]:
(1, 2, [7, 11, 5])

常见元组操作方法

  • tup.index(x, [start, [stop]])) 返回元组中start到stop索引中第一个值为 x 的元素在整个列表中的索引。如果没有匹配的元素就会返回一个错误。
  • tup.count(x) 返回 x 在元组中出现的次数。
  • len(tuple) 计算元组元素个数。
  • max(tuple) 返回元组中元素最大值。
  • min(tuple) 返回元组中元素最小值。
  • tuple(seq) 将列表转换为元组。
  • 元组不提供字符串、列表和字典中的方法。如果相对元组排序,通常先得将它转换为列表并使其成为一个可变对象,才能获得使用排序方法,或使用sorted内置方法。

1.9 集合

与dict类似,set也是一组key的集合,但不存储value。由于key不能重复,所以,在set中,没有重复的key。创建一个set,需要提供一个list作为输入集合

In [23]:
s = set([3,4,5])
s
Out[23]:
{3, 4, 5}

重复元素在set中会被自动被过滤,通过add(key)方法往set中添加元素,重复添加不会有效果,通过remove(key)方法可以删除元素,通过update([key1, key2, …])方法往set中添加多个元素,例如:

In [24]:
s = set([3,3,4,4,5,5,6,6,7])
s
Out[24]:
{3, 4, 5, 6, 7}
In [25]:
s.add(1)
s
Out[25]:
{1, 3, 4, 5, 6, 7}
In [26]:
s.remove(5)
s
Out[26]:
{1, 3, 4, 6, 7}
In [27]:
s.update([8, 9])
s
Out[27]:
{1, 3, 4, 6, 7, 8, 9}

由于set是无序和无重复元素的集合,所以两个set可以做数学意义上的交并集等操作

In [28]:
s1 = set([3,4,5,6])
s2 = set([5,6,7,8,9])

# 交集
s1 & s2
Out[28]:
{5, 6}
In [29]:
# 并集
s1 | s2
Out[29]:
{3, 4, 5, 6, 7, 8, 9}
In [30]:
# 差集
s2 - s1
Out[30]:
{7, 8, 9}
In [31]:
# 对称差集
s1 ^ s2
Out[31]:
{3, 4, 7, 8, 9}

与dict一样,set同样不可以放入可变对象,因为无法判断两个可变对象是否相等,也就无法保证set内部不会有重复元素。所以把list放入set,会报错

In [32]:
s = set([1,2,[1,2]])
Out[32]:
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-32-8190f4a1d44e> in <module>()
----> 1 s = set([1,2,[1,2]])

TypeError: unhashable type: 'list'

 

 

Python编程系列目录:
1. Python编程系列1-变量、字符串与列表
当前阅读>2.Python编程系列2-字典、元组与集合
3. Python编程系列3-条件与循环
4. Python编程系列4-函数
5. Python编程系列5-Numpy库
6. Python编程系列6-Scipy库
7. Python编程系列7-Pandas库
8. Python编程系列8-Matplotlib库