Python 字典默认值

Python 字典默认值,Python的字典有一个get()方法,在查找键的时候会提供备选值。这个方法适用于许多情况。下面通过一个简单的例子演示一下。假设有以下数据结构将用户ID映射到用户名:

name_for_userid = {
    382: 'Alice',
    950: 'Bob',
    590: 'Dilbert',
}

现在想用这个数据结构编写一个greeting()函数,根据用户ID向用户返回问候语。第一个实现看起来可能像这样:

def greeting(userid):
    return 'Hi %s!' % name_for_userid[userid]

这进行了直观的字典查找。不过这个实现只有在用户ID位于name_for_userid字典中时才能正常工作。如果向greeting函数传递无效的用户ID则会抛出异常:

>>> greeting(382)
'Hi Alice!'

>>> greeting(33333333)
KeyError: 33333333

我们并不希望看到KeyError异常,因此最好在找不到用户ID时,让函数返回一个通用的问候语作为备选。
下面来实现这个想法。首先想到的可能是在字典中查找键,如果找不到这个用户ID就返回默认问候语:

def greeting(userid):
    if userid in name_for_userid:
        return 'Hi %s!' % name_for_userid[userid]
    else:
        return 'Hi there!'

对这个greeting()实现使用之前的测试用例:

>>> greeting(382)
'Hi Alice!'

>>> greeting(33333333)
'Hi there!'

好多了,未知用户现在会得到通用的问候语,而在找到有效用户ID时会得到个性化的问候语。
虽然这个新实现能得到预期的结果,并且看起来短小简洁,但仍然可以改进。目前的方法有如下几个缺点。

  • 效率低下,需要查询字典两次。

  • 冗长,问候字符串有些重复。

  • 不够有Python特色,官方Python文档特别建议使用“请求原谅比获得许可要容易”(easier to ask for forgiveness than permission,EAFP)的编码风格:

这种通用的Python编码风格会先假定存在有效的键或属性,如果假设错误再捕获异常。

基于EAFP原则还有一种更好的实现,即不显式检查键是否包含在内,而是使用try...except块捕获KeyError

def greeting(userid):
    try:
        return 'Hi %s!' % name_for_userid[userid]
    except KeyError:
        return 'Hi there'

这种实现也满足最初的要求,而且无须查询字典两次。
然而还能将其进一步改进成更简洁的方案。Python的字典上有get()方法,其中可以传递一个用作备选值的“默认”参数:

def greeting(userid):
    return 'Hi %s!' %
        name_for_userid.get( userid, 'there')

当调用get()时,它会检查字典中是否存在给定的键。如果存在,则返回该键对应的值。如果存在,则返回默认的备选值。从上面可以看到,这个greeting的实现仍然按照预期工作:

>>> greeting(950)
'Hi Bob!'

>>> greeting(333333)
'Hi there!'

最终版的greeting()实现干净简洁,只用到了Python标准库中的特性。因此我认为这是针对这种特殊情况的最佳解决方案。

关键要点

  • 测试包含关系时应避免显式检查字典的键

  • 建议使用EAFP风格的异常处理或使用内置的get()方法。

  • 在某些情况下,可以使用标准库中的collections.defaultdict类。

Python教程

Java教程

Web教程

数据库教程

图形图像教程

大数据教程

开发工具教程

计算机教程