Python 第四章 字典

字典

  • 映射(mapping),一种可通过名称来访问其各个值的数据结构。

  • 字典是Python中唯一的内置映射类型,其中的值不按顺序排列,而是存储在键下。

  • 键可能是数、字符串或元组。

  • 在很多情况下,使用字典都比使用列表更合适。下面是Python字典的一些用途:

    表示棋盘的状态,其中每个键都是由坐标组成的元组;
    存储文件修改时间,其中的键为文件名;
    数字电话/地址簿。

  • 字典以类似于下面的方式表示:

    phonebook = {'Alice': '2341', 'Beth': '9102', 'Cecil': '3258'}
    
  • 字典由键及其相应的值组成,这种键-值对称为项(item)。

  • 每个键与其值之间都用冒号(:)分隔,项之间用逗号分隔,而整个字典放在花括号内。

  • 空字典(没有任何项)用两个花括号表示,类似于下面这样:{}

  • 在字典(以及其他映射类型)中,键必须是独一无二的,而字典中的值无需如此。

  • 函数**dict()**可以从其他映射(如其他字典)或键-值对序列创建字典。

    >>> items = [('name', 'Gumby'), ('age', 42)] 
    >>> d = dict(items) 
    >>> d 
    {'age': 42, 'name': 'Gumby'} 
    >>> d['name'] 
    'Gumby' 
    
  • 还可使用关键字实参来调用这个函数。

    >>> d = dict(name='Gumby', age=42) 
    >>> d 
    {'age': 42, 'name': 'Gumby'}
    
  • 也可使用一个映射实参来调用它,这将创建一个字典,其中包含指定映射中的所有项。

  • 从映射创建字典时,如果该映射也是字典(毕竟字典是Python中唯一的内置映射类型),可不使用函数dict(),而是使用字典方法copy(),

  • 字典的基本行为在很多方面都类似于序列。

    len(d) 返回字典d包含的项(键-值对)数。
    d[k] 返回与键k相关联的值。
    d[k] = v 将值v关联到键k。
    del d[k] 删除键为k的项。
    k in d 检查字典d是否包含键为k的项。

  • 键的类型:字典中的键可以是整数,但并非必须是整数。字典中的键可以是任何不可变的类型,如浮点数(实数)、字符串或元组。

  • 自动添加:即便是字典中原本没有的键,也可以给它赋值,这将在字典中创建一个新项。然而,如果不使用append或其他类似的方法,就不能给列表中没有的元素赋值。

  • 成员资格:表达式k in d(其中d是一个字典)查找的是键而不是值,而表达式v in l(其中l是一个列表)查找的是值而不是索引。这看似不太一致,但你习惯后就会觉得相当自然。毕竟如果字典包含指定的键,检查相应的值就很容易。

  • 例子:

    # 一个简单的数据库
    # 一个将人名用作键的字典。每个人都用一个字典表示,
    # 字典包含键'phone'和'addr',它们分别与电话号码和地址相关联
    people = { 
     'Alice': { 
     'phone': '2341', 
     'addr': 'Foo drive 23' 
     }, 
     'Beth': { 
     'phone': '9102', 
     'addr': 'Bar street 42' 
     }, 
     'Cecil': { 
     'phone': '3158', 
     'addr': 'Baz avenue 90' 
     } 
    } 
    # 电话号码和地址的描述性标签,供打印输出时使用
    labels = { 
     'phone': 'phone number', 
     'addr': 'address' 
    } 
    name = input('Name: ') 
    # 要查找电话号码还是地址?
    request = input('Phone number (p) or address (a)? ') 
    # 使用正确的键:
    if request == 'p': key = 'phone' 
    if request == 'a': key = 'addr' 
    # 仅当名字是字典包含的键时才打印信息:
    if name in people: print("{}'s {} is {}.".format(name, labels[key], people[name][key])) 
    
  • 运行结果:

    Name: Beth 
    Phone number (p) or address (a)? p 
    Beth's phone number is 9102.
    
  • 在字典中包含各种信息,这样只需在格式字符串中提取所需的信息即可。为此,必须使用format_map来指出通过一个映射来提供所需的信息。

    >>> phonebook 
    {'Beth': '9102', 'Alice': '2341', 'Cecil': '3258'} 
    >>> "Cecil's phone number is {Cecil}.".format_map(phonebook) 
    "Cecil's phone number is 3258."
    
  • 样使用字典时,可指定任意数量的转换说明符,条件是所有的字段名都是包含在字典中的键。在模板系统中,这种字符串格式设置方式很有用

    >>> template = '''<html> 
    ... <head><title>{title}</title></head> 
    ... <body> 
    ... <h1>{title}</h1> 
    ... <p>{text}</p>
    ... </body>''' 
    >>> data = {'title': 'My Home Page', 'text': 'Welcome to my home page!'} 
    >>> print(template.format_map(data)) 
    <html> 
    <head><title>My Home Page</title></head> 
    <body> 
    <h1>My Home Page</h1> 
    <p>Welcome to my home page!</p> 
    </body>
    
  • 方法**clear()**删除所有的字典项,这种操作是就地执行的(就像list.sort一样),因此什么都不返回(或者说返回None)。

    >>> d = {} 
    >>> d['name'] = 'Gumby' 
    >>> d['age'] = 42 
    >>> d 
    {'age': 42, 'name': 'Gumby'} 
    >>> returned_value = d.clear() 
    >>> d 
    {} 
    >>> print(returned_value) 
    None
    
  • 在下面这两个案例中,x和y最初都指向同一个字典。在案例一中,通过将一个空字典赋给x来“清空”它。这对y没有任何影响,它依然指向原来的字典。如果要删除原来字典的所有元素,必须使用clear。这样做,y也将是空的,如案例二所示。

  • 案例一:

    >>> x = {}
    >>> y = x
    >>> x['name'] = 'wmd'
    >>> x
    {'name': 'wmd'}
    >>> y
    {'name': 'wmd'}
    >>> x = {}
    >>> x
    {}
    >>> y
    {'name': 'wmd'}
    
  • 案例二:

    >>> x = {}
    >>> y = x
    >>> x['name'] = 'wmd'
    >>> y
    {'name': 'wmd'}
    >>> x.clear()
    >>> y
    {}
    
  • 方法**copy()**返回一个新字典,其包含的键-值对与原来的字典相同(这个方法执行的是浅复制,因为值本身是原件,而非副本)

  • 当替换副本中的值时,原件不受影响。然而,如果修改副本中的值(就地修改而不是替换),原件也将发生变化,因为原件指向的也是被修改的值.

    >>> x = {'username': 'admin', 'machines': ['foo', 'bar', 'baz']} 
    >>> y = x.copy() 
    >>> y['username'] = 'mlh' 
    >>> y['machines'].remove('bar') 
    >>> y 
    {'username': 'mlh', 'machines': ['foo', 'baz']} 
    >>> x 
    {'username': 'admin', 'machines': ['foo', 'baz']}
    
  • 为避免这种问题,一种办法是执行深复制,即同时复制值及其包含的所有值,等等。为此,可使用模块copy中的函数deepcopy()

    >>> from copy import deepcopy 
    >>> d = {} 
    >>> d['names'] = ['Alfred', 'Bertrand'] 
    >>> c = d.copy() 
    >>> dc = deepcopy(d) 
    >>> d['names'].append('Clive') 
    >>> c 
    {'names': ['Alfred', 'Bertrand', 'Clive']} 
    >>> dc 
    {'names': ['Alfred', 'Bertrand']}
    
  • 方法**fromkeys()**创建一个新字典,其中包含指定的键,且每个键对应的值都是None。

    >>> {}.fromkeys(['name', 'age']) 
    {'age': None, 'name': None}
    
  • 是直接对dict调用方法fromkeys()。

    >>> dict.fromkeys(['name', 'age']) 
    {'age': None, 'name': None}
    
  • 如果不想使用默认值None,可提供特定的值。

    >>> dict.fromkeys(['name', 'age'], '(unknown)') 
    {'age': '(unknown)', 'name': '(unknown)'}
    
  • 方法**get()**为访问字典项提供了宽松的环境。

  • 通常,如果试图访问字典中没有的项,将引发错误,而使用get不会这样。

    >>> d = {} 
    >>> print(d['name']) 
    Traceback (most recent call last): 
     File "<stdin>", line 1, in ? 
    KeyError: 'name'
    >>> print(d.get('name')) 
    None
    
  • 使用get来访问不存在的键时,没有引发异常,而是返回None。你可指定“默认”值,这样将返回你指定的值而不是None。

    >>> d.get('name', 'N/A') 
    'N/A'
    
  • 例子:

    # 一个使用get()的简单数据库
    people = { 
     'Alice': { 
     'phone': '2341', 
     'addr': 'Foo drive 23' 
     }, 
     'Beth': { 
     'phone': '9102', 
     'addr': 'Bar street 42' 
     }, 
     'Cecil': { 
     'phone': '3158', 
     'addr': 'Baz avenue 90' 
     } 
    }
    labels = { 
     'phone': 'phone number', 
     'addr': 'address' 
    } 
    name = input('Name: ') 
    # 要查找电话号码还是地址?
    request = input('Phone number (p) or address (a)? ') 
    # 使用正确的键:
    key = request # 如果request既不是'p'也不是'a' 
    if request == 'p': key = 'phone' 
    if request == 'a': key = 'addr' 
    # 使用get提供默认值
    person = people.get(name, {}) 
    label = labels.get(key, key) 
    result = person.get(key, 'not available') 
    print("{}'s {} is {}.".format(name, label, result))
    
  • 结果:

    Name: Gumby 
    Phone number (p) or address (a)? batting average 
    Gumby's batting average is not available.
    
  • 方法**items()**返回一个包含所有字典项的列表,其中每个元素都为(key, value)的形式。字典项在列表中的排列顺序不确定。

    >>> d = {'title': 'Python Web Site', 'url': 'http://www.python.org', 'spam': 0} 
    >>> d.items() 
    dict_items([('url', 'http://www.python.org'), ('spam', 0), ('title', 'Python Web Site')])
    
  • 返回值属于一种名为字典视图的特殊类型。字典视图可用于迭代。

  • 视图的一个优点是不复制,它们始终是底层字典的反映,即便你修改了底层字典亦如此.

    >>> d['spam'] = 1 
    >>> ('spam', 0) in it 
    False 
    >>> d['spam'] = 0 
    >>> ('spam', 0) in it 
    True
    
  • 将字典项复制到列表中。

    >>> list(d.items()) 
    [('spam', 0), ('title', 'Python Web Site'), ('url', 'http://www.python.org')]
    
  • 方法**keys()**返回一个字典视图,其中包含指定字典中的键。

    >>> a = {'name':'wmd', 'age':18}
    >>> b = a.keys()
    >>> b
    dict_keys(['name', 'age'])
    >>>
    
  • 方法**pop()**可用于获取与指定键相关联的值,并将该键-值对从字典中删除。

    >>> d = {'x': 1, 'y': 2} 
    >>> d.pop('x') 
    1 
    >>> d 
    {'y': 2}
    
  • 方法**popitem()**类似于list.pop,但list.pop弹出列表中的最后一个元素,而popitem随机地弹出一个字典项,因为字典项的顺序是不确定的,没有“最后一个元素”的概念。如果你要以高效地方式逐个删除并处理所有字典项,这可能很有用,因为这样无需先获取键列表。

    >>> d = {'url': 'http://www.python.org', 'spam': 0, 'title': 'Python Web Site'} 
    >>> d.popitem() 
    ('url', 'http://www.python.org') 
    >>> d 
    {'spam': 0, 'title': 'Python Web Site'}
    
  • 虽然popitem类似于列表方法pop,但字典没有与append(它在列表末尾添加一个元素)对应的方法。这是因为字典是无序的,类似的方法毫无意义。

  • 方法**setdefault()**有点像get,因为它也获取与指定键相关联的值,但除此之外,setdefault还在字典不包含指定的键时,在字典中添加指定的键-值对。

    >>> d = {} 
    >>> d.setdefault('name', 'N/A') 
    'N/A' 
    >>> d 
    {'name': 'N/A'} 
    >>> d['name'] = 'Gumby' 
    >>> d.setdefault('name', 'N/A') 
    'Gumby' 
    >>> d 
    {'name': 'Gumby'}
    
  • 指定的键不存在时,setdefault返回指定的值并相应地更新字典。如果指定的键存在,就返回其值,并保持字典不变。与get一样,值是可选的;如果没有指定,默认为None。

    >>> d = {} 
    >>> print(d.setdefault('name')) 
    None 
    >>> d 
    {'name': None}
    
  • 方法**update()**使用一个字典中的项来更新另一个字典。

  • 对于通过参数提供的字典,将其项添加到当前字典中。如果当前字典包含键相同的项,就替换它。

    >>> d = { 
    ... 'title': 'Python Web Site', 
    ... 'url': 'http://www.python.org', 
    ... 'changed': 'Mar 14 22:09:15 MET 2016' 
    ... }
    >>> x = {'title': 'Python Language Website'} 
    >>> d.update(x) 
    >>> d 
    {'url': 'http://www.python.org', 'changed': 
    'Mar 14 22:09:15 MET 2016', 'title': 'Python Language Website'}
    
  • 方法values返回一个由字典中的值组成的字典视图。不同于方法keys,方法values返回的视图可能包含重复的值。

    >>> d = {} 
    >>> d[1] = 1 
    >>> d[2] = 2 
    >>> d[3] = 3 
    >>> d[4] = 1 
    >>> d.values() 
    dict_values([1, 2, 3, 1])
    
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值