除了字符串和整数之外的Python字典键?

Python dictionary keys besides strings and integers?

任何人都有一些简洁的字典示例,其中包含一些有趣的键(除了规范字符串或整数),以及如何在程序中使用这些键?

我知道我们对一个键所需要的就是hashable,这意味着它必须是不变的和可比较的(有__eq__()__cmp__()方法)。

一个相关的问题是:我如何快速而巧妙地定义一个新的hashable


我们去做些更深奥的事吧。假设您想要执行一个函数列表并存储每个函数的结果。对于每一个引发异常的函数,您需要记录异常,并且还需要对每一种异常引发的次数进行计数。函数和异常可以用作dict键,因此这很容易:

1
2
3
4
5
6
7
8
9
10
11
12
funclist = [foo, bar, baz, quux]

results    = {}
badfuncs   = {}
errorcount = {}

for f in funclist:
    try:
        results[f] = f()
    except Exception as e:
        badfuncs[f]   = e
        errorcount[type(e)] = errorcount[type(e)] + 1 if type(e) in errorcount else 1

现在您可以执行if foo in badfuncs来测试该函数是否引发了异常(或if foo in results来查看它是否正常运行),if ValueError in errorcount来查看是否有函数引发了ValueError等等。


例如,如果要创建多列索引,可以使用元组作为键。下面是一个简单的例子:

1
2
3
4
5
6
7
>>> index = {("John","Smith","1972/01/01"): 123, ("Bob","Smith","1972/01/02"): 124}
>>> index
{('Bob', 'Smith', '1972/01/02'): 124, ('John', 'Smith', '1972/01/01'): 123}
>>> index.keys()
[('Bob', 'Smith', '1972/01/02'), ('John', 'Smith', '1972/01/01')]
>>> index['John', 'Smith', '1972/01/01']
123

有关如何将dict用作键(可哈希dict)的示例,请参见以下答案:python可哈希字典


对于对象来说,可能最重要的方法是hashable:__hash__()

您自己的哈希类型的最短实现是:

1
2
class A(object):
    pass

现在您可以使用A的实例作为字典键:

1
2
3
4
5
d = {}
a = A()
b = A()
d[a] = 7
d[b] = 8

这是因为用户定义的类在默认情况下是可以散列的,它们的散列值是它们的ID——所以只有当它们是相同的对象时,它们才会进行相等的比较。

请注意,A的实例决不是不可变的,它们仍然可以用作字典键。字典键必须是不可变的语句只能用于内置类型。


注意,我从来没有真正使用过这个,但我一直认为使用元组作为键可以让你做一些有趣的事情。例如,我会发现它是一种绘制网格坐标的方便方法。你可以把它想象成一个电子游戏上的网格(也许是某种战术游戏,比如火徽):

1
2
3
4
5
6
7
8
9
10
11
>>> Terrain = { (1,3):"Forest", (1,5):"Water", (3,4):"Land" }
>>> print Terrain
{(1, 5): 'Water', (1, 3): 'Forest', (3, 4): 'Land'}
>>> print Terrain[(1,3)]
Forest
>>> print Terrain[(1,5)]
Water
>>> x = 3
>>> y = 4
>>> print Terrain[(x,y)]
Land

像那样。

编辑:正如马克·拉沙科夫在评论中所指出的,我基本上打算把它作为一个稀疏数组。


我不知道你为什么要这样做(最好不要这样做)。但是除了字符串和整数之外,您还可以同时使用这两者。也就是说,作为一个初学者,我发现它既强大又令人惊讶:

1
foo = { 1:'this', 2:'that', 'more':'other', 'less':'etc' }

是一个完全有效的字典,它提供对foo[2]的访问和对foo['more']的访问一样容易。