python映射的主要特点_Python基础:映射(字典)

一、概述

映射类型(Mapping Types)是一种关联式的容器类型,它存储了对象与对象之间的映射关系。

字典(dict)是Python中唯一的映射类型,它是存储了一个个 键值对(由 键 映射到 值)的关联容器。其中,键(key)必须是可哈希的Python对象,而 值(value)可以是任何Python对象。在功能上,Python中的字典类似于C++中的map。

Python中最强大、最灵活的数据类型当属 列表 和 字典,以下是对这两种数据类型的简单比较:

比较点列表字典

表示方法

[],[1, 2]

{},{'a': 1, 'b': 2}

访问元素的方式

索引

有序性

有序

无序

可变性

可变

可变

可操作性

操作丰富

操作丰富

表征的数据结构

数组、堆栈、队列等

哈希表等

二、操作

字典支持的主要操作如下:

操作说明

class dict(other)

创建字典(other可以是字典、(key, value)对的迭代器或关键字参数)

dict.fromkeys(seq[, value])

创建字典:用序列seq中的元素作为键,值全为value(未指定,则默认为None)

len(d)

返回字典d的长度(即d中元素的个数)

d[key]

如果键key在字典d中,则返回其中key对应的值;否则抛出KeyError异常

d[key] = value

设置d[key]的值为value(存在则修改,不存在则添加)

del d[key]

如果键key在字典d中,则从字典d中删除d[key];否则抛出KeyError异常

key in d

如果key在字典d中,返回True;否则,返回False

key not in d

如果key在字典d中,返回False;否则,返回True

iter(d)

同iterkeys()

d.clear()

删除字典d中的所有元素

d.copy()

返回字典d的浅拷贝

d.get(key[, default])

如果key在字典d中,则返回d[key];否则返回default(未指定,则默认为None)

d.has_key(key)

同key in d(推荐使用key in d)

d.items()

返回包含字典d中的(key, value)对的列表

d.iteritems()

迭代版的items():返回迭代器

d.iterkeys()

迭代版的keys():返回迭代器

d.itervalues()

迭代版的values():返回迭代器

d.keys()

返回包含字典d中的键的列表

d.pop(key[, default])

如果key在字典d中,则返回并删除d[key];否则返回default(未指定,则抛出KeyError异常)

d.popitem()

返回并删除字典d中的任意一个元素(如果d为空,则抛出KeyError异常)

d.setdefault(key[, default])

如果key在字典d中,则返回d[key];否则执行d[key] = default,并返回default(未指定,则默认为None)

d.update([other])

将other中的(key, value)对添加到字典d中(other可以是字典、(key, value)对的迭代器或关键字参数)

d.values()

返回包含字典d中的值的列表

d.viewitems()

返回字典d的元素视图

d.viewkeys()

返回字典d的键视图

d.viewvalues()

返回字典d的值视图

以上操作的示例如下:

>>> a = {'one': 1, 'two': 2, 'three': 3}

>>> b = dict(one=1, two=2, three=3)

>>> c = dict(zip(['one', 'two', 'three'], [1, 2, 3]))

>>> d = dict({'three': 3, 'one': 1, 'two': 2})

>>> a == b == c == d

True

>>> d = dict.fromkeys(['a', 'b', 'c'])

>>> d

{'a': None, 'c': None, 'b': None}

>>> d = dict.fromkeys(['a', 'b', 'c'], 6)

>>> d

{'a': 6, 'c': 6, 'b': 6}

>>> len(d)

3

>>> d.clear()

>>> d

{}

>>> d = a.copy()

>>> d

{'one': 1, 'three': 3, 'two': 2}

>>> d['three']

3

>>> d['four'] = 4

>>> d

{'four': 4, 'one': 1, 'three': 3, 'two': 2}

>>> del d['one']

>>> d

{'four': 4, 'three': 3, 'two': 2}

>>> 'four' in d, 'four' not in d

(True, False)

>>> d.has_key('four')

True

>>> d.get('one'), d.get('one', 10)

(None, 10)

>>> for k in d:

... print k,

...

four three two

>>> for k in iter(d):

... print k,

...

four three two

>>> for k in d.keys():

... print k,

...

four three two

>>> for k in d.iterkeys():

... print k,

...

four three two

>>> for k in d.viewkeys():

... print k,

...

four three two

>>> for v in d.values():

... print v,

...

4 3 2

>>> for v in d.itervalues():

... print v,

...

4 3 2

>>> for v in d.viewvalues():

... print v,

...

4 3 2

>>> for i in d.items():

... print i,

...

('four', 4) ('three', 3) ('two', 2)

>>> for i in d.iteritems():

... print i,

...

('four', 4) ('three', 3) ('two', 2)

>>> for i in d.viewitems():

... print i,

...

('four', 4) ('three', 3) ('two', 2)

>>> d.setdefault('two')

2

>>> d

{'four': 4, 'three': 3, 'two': 2}

>>> d.setdefault('one', 1)

1

>>> d

{'four': 4, 'one': 1, 'three': 3, 'two': 2}

>>> d.update(five=1)

>>> d

{'four': 4, 'one': 1, 'five': 1, 'three': 3, 'two': 2}

>>> d.update({'six': 6})

>>> d

{'four': 4, 'five': 1, 'two': 2, 'six': 6, 'three': 3, 'one': 1}

>>> d.pop('four')

4

>>> d

{'five': 1, 'two': 2, 'six': 6, 'three': 3, 'one': 1}

>>> d.popitem()

('five', 1)

>>> d

{'two': 2, 'six': 6, 'three': 3, 'one': 1}

三、字典特性

1、有序与无序

从概念上讲,字典提供了这样一种抽象:容器中的元素之间完全独立(于是也没有先后顺序),“键”是访问元素的唯一方式。在这种 抽象层面 上,字典是 无序 的。

从实现上讲,字典其实是由 哈希表 实现的。而哈希表的基本思想是:通过 哈希函数(hash function)将“键”转换为“索引”,再使用“索引”去访问 连续列表(如C中的数组)中的元素。由此可知,在哈希表中:一方面,元素本质上是存储在一个连续列表中的,因此是 有序 的;另一方面,用户无法确定元素在连续列表中的实际位置(只能使用“键”去访问元素,而“键”与“索引”的映射关系是由哈希函数在内部指定的),因此又是 无序 的。

因此在 实现层面 上,字典同时具备了 无序 和 有序 的特点:

无序体现在:字典中元素的排列顺序与添加顺序无关

有序体现在:在字典保持不变的情况下,字典中元素的排列顺序是固定的

03205642-0eef778bee744f6fa5390f83649d7349.png

上图对应的示例如下:

# 无序

>>> d = {}

>>> d['a'] = 1

>>> d

{'a': 1}

>>> d['b'] = 2

>>> d

{'a': 1, 'b': 2}

>>> d['c'] = 3

>>> d

{'a': 1, 'c': 3, 'b': 2}

# 有序

>>> for k in d: # 键的顺序固定

... print k,

...

a c b

>>> for v in d.values(): # 值的顺序固定

... print v,

...

1 3 2

>>> for i in d.items(): # 元素的顺序固定

... print i,

...

('a', 1) ('c', 3) ('b', 2)

2、字典的键

字典的键具有以下特性:

1)可哈希的(hashable)

只有 可哈希的 对象才能作为字典的键,一个可哈希的对象必须满足以下两个条件:

该对象在其生命周期内有一个不变的哈希值(需要实现__hash__()方法)

该对象是可比较的(需要实现__eq__()或__cmp__()方法)

Python中可哈希的对象有:

数值、字符串,以及只含有数值或字符串的元组

用户自定义类的实例(默认是可哈希的,也可以通过实现__hash__()和__cmp__()来修改默认行为)

2)哈希等价键

假设有字典d的两个键:keyA和keyB,我们称keyA和keyB是 哈希等价键(自己杜撰的名词),如果keyA和keyB满足以下两个条件:

hash(keyA) == hash(keyB)

cmp(keyA, keyB) == 0

如果keyA和keyB是哈希等价键,那么它们将被视为完全相同的两个键,于是d[keyA]和d[keyB]会指向同一个字典元素。

例如,1和1.0就满足上述两个条件,因此是哈希等价键:

>>> hash(1), hash(1.0)

(1, 1)

>>> cmp(1, 1.0)

0

>>> d = {}

>>> d[1] = 'int 1'

>>> d

{1: 'int 1'}

>>> d[1.0] = 'float 1'

>>> d

{1: 'float 1'}

对于用户自定义的类实例,默认情况下(即没有实现__hash__()和__cmp__()时),hash(...)和cmp(...)的结果与 id() 有关(参考 hashable 和 __cmp__())。默认情况下,一个自定义类的任意两个实例都不是哈希等价键:

>>> class A: pass

...

>>> a1 = A()

>>> a2 = A()

>>> hash(a1), hash(a2)

(-1064359592, -1064359600)

>>> cmp(a1, a2)

1

>>> d = {}

>>> d[a1] = 'a1'

>>> d

{<__main__.A instance at 0x8f2958c>: 'a1'}

>>> d[a2] = 'a2'

>>> d

{<__main__.A instance at 0x8f2958c>: 'a1', <__main__.A instance at 0x8f2950c>: 'a2'}

如果想要让同一个类的任意两个实例都是哈希等价键,则可以参考以下示例:

>>> class A:

... def __hash__(self):

... return hash(A)

... def __cmp__(self, other):

... return cmp(self.__hash__(), other.__hash__())

...

>>> a1 = A()

>>> a2 = A()

>>> hash(a1), hash(a2)

(-1064346499, -1064346499)

>>> cmp(a1, a2)

0

>>> d = {}

>>> d[a1] = 'a1'

>>> d

{<__main__.A instance at 0x8f64a4c>: 'a1'}

>>> d[a2] = 'a2'

>>> d

{<__main__.A instance at 0x8f64a4c>: 'a2'}

类似地,如果想要让一个类的任意一个实例与整数1成为哈希等价键,则可以按照以下方式实现:

>>> class A:

... def __hash__(self):

... return 1

... def __cmp__(self, other):

... return cmp(self.__hash__(), other.__hash__())

...

>>> a = A()

>>> hash(1), hash(a)

(1, 1)

>>> cmp(1, a)

0

>>> d = {}

>>> d[1] = 'int 1'

>>> d

{1: 'int 1'}

>>> d[a] = 'instance a'

>>> d

{1: 'instance a'}

四、字典视图

从2.7版本开始,Python中引入了字典视图(Dictionary views)。字典视图 是字典的 动态视图:它们会与字典保持同步,实时反应出字典的变化。字典视图共有3种:键视图(Keys views)、值视图(Values views)和 元素视图(Items views),它们分别由dict.viewkeys()、dict.viewvalues()和dict.viewitems()三个函数返回。

所有的字典视图都支持以下操作:

操作说明

len(dictview)

返回字典的长度

iter(dictview)

返回(键、值、元素)迭代器

x in dictview

判断x是否为(键、值、元素)的成员

此外,因为字典的键是 唯一 且 可哈希的,所以 键视图 还支持 类似集合(set-like)的操作。如果字典的值是 可哈希的,那么 元素视图 也支持这些操作:

操作说明

dictview & other

求交集

dictview | other

求并集

dictview - other

求差集

dictview ^ other

求对称差集

五、应用

1、模拟switch-case语句

以下是C中一个使用switch-case语句的示例:

int select(char c)

{

int num = -1;

switch (c)

{

case 'a':

num = 1;

break;

case 'b':

num = 2;

break;

case 'c':

num = 3;

break;

default:

num = 0;

break;

}

return num;

}

Python中没有提供switch-case语句,但使用字典可以轻松实现类似上面的功能:

d = {'a': 1, 'b': 2, 'c': 3}

# 普通版本

def select1(c):

num = -1

if c not in d:

num = 0

else:

num = d[c]

return num

# 惊呆版本

def select2(c):

return d.get(c, 0)

2、稀疏矩阵

使用元组作为字典的键,可以构建类似稀疏矩阵的数据结构:

>>> matrix = {}

>>> matrix[(2, 3, 4)] = 88

>>> matrix[(7, 8, 9)] = 99

>>>

>>> matrix

{(2, 3, 4): 88, (7, 8, 9): 99}

>>>

>>> x, y, z = 2, 3, 4

>>> matrix[(x, y, z)]

88

3、符号表

实际上,Python本身就在内部大量使用了字典,一个典型的应用就是符号表:

>>> locals() # 局部符号表

{'__builtins__': , '__name__': '__main__', '__doc__': None, '__package__': None}

>>> globals() # 全局符号表

{'__builtins__': , '__name__': '__main__', '__doc__': None, '__package__': None}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值