Skip to main content
 首页 » 编程设计

python之Python 3.x 中的字典采样

2025年05月04日13linjiqin

在 Python 3 中,dict_values、dict_keys 和 dict_items 不支持索引

my_dict = {'a': 0', 'b': 1', 'c': 2} 

以下所有查询均失败:

my_dict.keys()[1] 
my_dict.values()[1] 
my_dict.items()[1] 

出于这个原因。

有时我只想随机抽取字典中的内容。我知道我可以将它们的输出转换为列表。他们是否有任何其他不需要创建另一个数据结构的 getter 方法? (我还认为将它们转换为列表会创建一个副本,这可能不适用于大型词典)。

请您参考如下方法:

Sometimes I just want to get a random sample of what's in my dictionary. I know I can convert them their output to lists. Do they have any other getter methods that do not require creating another data structure? (I would also imagine that converting them to a list would create a copy, which may not work well for huge dictionaries).

key 类型在 Dictionary view objects 下进行了解释, 并且也保证是 collections.abc.KeysView 的子类和 friend 。基本上,这意味着您只能指望它们具有 __contains__、__iter__ 和 __len__。

它们不直接支持索引,因为它们的顺序可能会失效。*但实际上,在 Python 的任何实现中,只有当您改变字典时它们才会真正失效。这意味着你可以安全地做这样的事情:

next(itertools.islice(my_dict.keys(), i, None)) 

基本上,与索引 set 或任何其他可迭代的非迭代器的方式相同。

* 关于记录哪些行为的实际规则已经更改了几次。当前版本实际上说“他们提供了字典条目的动态 View ,这意味着当字典发生变化时, View 会反射(reflect)这些变化”,这意味着现在可以依赖实用规则。但是,即使您使用的是旧版本,例如,它明确地只保证对 keys、values、items 和相关函数,除非您担心有人编写 Python 2.6 或 3.1 或其他东西的新实现,否则没有理由为此担心。


当然,您可能希望将其包装在一个更具可读性的函数中。事实上,我会分两步来做。首先,使用 itertools recipes 中的 nth 函数:

def nth(iterable, n, default=None): 
    return next(itertools.islice(iterable, n, None), default) 

然后结束键索引:

def getkey(mapping, index, default=None): 
    return nth(mapping.keys(), index, default) 

如果你想要一个随机样本怎么办?好吧,字典 View 是 Sized 的,字典本身也是,所以您可以随时使用 randrange:

def choosekey(mapping): 
    return getkey(mapping, random.randrange(len(mapping)))