从非空 defaultdict 中选取一个随机元素

Picking a random element from a non-empty defaultdict

说我愿意:

import collections, random
d = collections.defaultdict(list)
d['foo'].append('bar')

然后我选择一个随机元素:

random.choice(d)

现在让我们打印 d:

defaultdict(list, {0: [], 'foo': ['bar']})

为什么 random.choice 添加 0 作为键?

在内部这是 random.choice 所做的:

def choice(self, seq):
    """Choose a random element from a non-empty sequence."""
    return seq[int(self.random() * len(seq))]

在你的例子中,长度是 1,乘法后它会产生一个范围 [0.0, 1.0) 的数字,在应用 int() 之后你会得到 0。

请注意,defaultdict 会将任何键添加到在其上访问的字典:

>>> d = collections.defaultdict(list)
>>> d['i dont exist']
[]
>>> d
defaultdict(<type 'list'>, {'i dont exist': []})

因此,您的命令以 0 结尾。

我认为该行为实际上是 未定义,因为根据文档(强调我的):

random.choice(seq)

Return a random element from the non-empty sequence seq. If seq is empty, raises IndexError.

seq需要是序列类型,例如listtuplerange。但是,defaultdict 是内置 dict class 的子class,因此它是一个 mapping 类型。

而且由于序列类型只能有整数作为它们的 "keys",所以 random.choice 会查找 d[x] 并不奇怪,其中 x 是 [= 中的整数20=].