jco*_*ctx 6 python perl hash dictionary
Perl有一个构造(如Joe Z所指出的那样称为"哈希切片"),用于索引到带有列表的哈希以获取列表,例如:
%bleah = (1 => 'a', 2 => 'b', 3 => 'c');
print join(' ', @bleah{1, 3}), "\n";
Run Code Online (Sandbox Code Playgroud)
执行给出:
a c
Run Code Online (Sandbox Code Playgroud)
我知道在Python中处理这个问题的最简单,最易读的方法是列表理解:
>>> bleah = {1: 'a', 2: 'b', 3: 'c'}
>>> print ' '.join([bleah[n] for n in [1, 3]])
a c
Run Code Online (Sandbox Code Playgroud)
因为:
>>> bleah[[1, 2]]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'list'
Run Code Online (Sandbox Code Playgroud)
我还有其他一些更好的方法吗?也许在Python3中,我还没有做过多少工作?如果没有,是否有人知道是否已经为此提交了PEP?我的google-fu无法找到一个.
"它不是Pythonic":是的,我知道,但我希望它能成为现实.它是简洁和可读性,因为它永远不会是Python的索引到与unhashable类型的字典,其在指数中的异常处理程序迭代为你而不是barfing不会打破目前大多数代码.
注意:正如评论中指出的那样,这个测试用例可以重写为一个列表,完全避免使用dict,但我正在寻找一个通用的解决方案.
我能想到的最好的方法是使用itemgetter
from operator import itemgetter
bleah = {1: 'a', 2: 'b', 3: 'c'}
getitems = itemgetter(1, 3)
print getitems(bleah)
Run Code Online (Sandbox Code Playgroud)
因此,如果您想传递索引列表,那么您可以解压缩参数,如下所示(感谢 @koffein 指出这一点:))
getitems = itemgetter(*[1, 3])
Run Code Online (Sandbox Code Playgroud)
然后你可以join喜欢这个
print ' '.join(getitems(bleah))
Run Code Online (Sandbox Code Playgroud)
或者简单地
print ' '.join(itemgetter(1, 3)(bleah))
Run Code Online (Sandbox Code Playgroud)
目前,我在评论中采纳 Hyperboreus 的建议并重写__getitem__,但我仍然认为将其作为默认的字典行为是有意义的:
jcomeau@aspire:~$ cat /tmp/sliceable.py; echo ---; python /tmp/sliceable.py\n'SliceableDict test'\nimport sys, os\nclass SliceableDict(dict):\n\xc2\xa0def __init__(self, d = {}):\n\xc2\xa0 super(SliceableDict, self).__init__(d)\n\xc2\xa0def __getitem__(self, index):\n\xc2\xa0 try:\n\xc2\xa0 \xc2\xa0return super(SliceableDict, self).__getitem__(index)\n\xc2\xa0 except TypeError:\n\xc2\xa0 \xc2\xa0return [super(SliceableDict, self).__getitem__(x) for x in index]\n\xc2\xa0def __setitem__(self, index, value):\n\xc2\xa0 try:\n\xc2\xa0 \xc2\xa0super(SliceableDict, self).__setitem__(index, value)\n\xc2\xa0 except:\n\xc2\xa0 \xc2\xa0for i in range(len(index)):\n\xc2\xa0 \xc2\xa0 super(SliceableDict, self).__setitem__(index[i], value[i])\nd = SliceableDict({1: 'a', 2: 'b', 3: 'c'})\nprint d[2]\nprint d[[1, 3]]\nd[[1, 3]] = ['x', 'y']\nprint d\n---\nb\n['a', 'c']\n{1: 'x', 2: 'b', 3: 'y'}\nRun Code Online (Sandbox Code Playgroud)\n\n(根据上面 tobyink 的评论修改为添加左值功能 -- jc 2013-12-12)
\n