2007-11-30

 

Python Cookbook 4.13 从字典中提取子集

需求:

我们需要从一个含有大量数据的字典中获取指定键集合的子集.

讨论:

如果需要保持原字典的完整性,可以这样写:

def sub_dict(somedict, somekeys, default=None):
    return dict([ (k, somedict.get(k, default)) for k in somekeys ])

如果想从原有字典中去除提取的子集,可以这样写:

def sub_dict_remove(somedict, somekeys, default=None):
    return dict([ (k, somedict.pop(k, default)) for k in somekeys ])

下面是两个例子:
>>> d = {'a': 5, 'b': 6, 'c': 7} 
>>> print sub_dict(d, 'ab'), d
{'a': 5, 'b': 6} {'a': 5, 'b': 6, 'c': 7}
>>> print sub_dict_remove(d, 'ab'), d
{'a': 5, 'b': 6} {'c': 7}
相关说明:

在Python中,有很多地方都会用到字典,比如表示数据库的行,主键和组合键,模板解析时的变量命名空间等.所以,我们经常会遇到需要基于一个字典来创建另一个.原来的字典包含有大量数据,而我们只需要其中的一部分.在大多数情况下,需要保持原数据不变,在某些情况下,则需要去除提取的数据.本节中讨论了两种情况的解决方案.两种方法的不同之处在于使用get来保持原数据不变 ,使用pop来去除提取数据.
如果有些情况下,在somedict字典中不包含somekey中的键key,本节的方法依然会有一个返回值,它使用了默认值(在函数声明的地方写的是None).所以,结果并不一定完全是somedict的子集.这样的需求在我自己的应用中是最多的.
也许你需要获得一个"键不存在"的异常,用于提示自己程序中可能有一个bug,它说明somekey中的有些key不是somedict中的键值.要注意: "错误永远不应默默的溜掉,除非明确的使用沉默",这是Python之禅的一句.所以,如果键不存在在你的应用程序中是一个错误,你需要立刻获得异常来提示用户,你可以将上面的代码稍微修改一下:
def sub_dict_strict(somedict, somekeys):
return dict([ (k, somedict[k]) for k in somekeys ])
def sub_dict_remove_strict(somedict, somekeys):
return dict([ (k, somedict.pop(k)) for k in somekeys ])
看,这个代码比以前的还要简单,这说明Python喜欢在不确定的情况下抛出异常!

或者,你需要忽略在somedict中不存在的key,可以这样修改:
 def sub_dict_select(somedict, somekeys):
return dict([ (k, somedict[k]) for k in somekeys if k in somedict])
def sub_dict_remove_select(somedict, somekeys):
return dict([ (k, somedict.pop(k)) for k in somekeys if k in somedict])
在递推式中的if语句实现了我们的需求,排除了不存在的key.
在Python2.4以后,你可以使用代码生成器,而不是递推式.仅仅把代码从dict([...])改为dict(...)即可.

关于Python之禅,使用import this即可.

This page is powered by Blogger. Isn't yours?