询问;是可散列的;关于Python值

询问;是可散列的;关于Python值,python,hash,Python,Hash,我感兴趣的是将一个任意的dict复制成一个新的dict,并在过程中对其进行变异 我想做的一个变化是交换键和值。不幸的是,有些价值观本身就是一成不变的。但是,这会生成一个“不可损坏类型:'dict'”错误。我真的不介意将值串起来,然后给它一个键。但是,我希望能够做到这样: for key in olddict: if hashable(olddict[key]): newdict[olddict[key]] = key else newdict[str(olddict[ke

我感兴趣的是将一个任意的dict复制成一个新的dict,并在过程中对其进行变异

我想做的一个变化是交换键和值。不幸的是,有些价值观本身就是一成不变的。但是,这会生成一个“不可损坏类型:'dict'”错误。我真的不介意将值串起来,然后给它一个键。但是,我希望能够做到这样:

for key in olddict:
  if hashable(olddict[key]):
    newdict[olddict[key]] = key
  else
    newdict[str(olddict[key])] = key

有没有一种干净的方法可以做到这一点,而不需要捕获异常并解析“不可损坏类型”的消息字符串?

因为Python 2.6可以使用抽象基类:

此方法在的文档中也有简要介绍

这样做意味着,当程序试图检索其哈希值时,类的实例不仅会引发适当的
TypeError
,而且在检查
isinstance(obj,collections.Hashable)
(与定义自己的
\uuuhash()的类不同)时,它们也会被正确标识为不可损坏
显式引发
TypeError


所有可哈希的内置python对象都有一个
。\uuuuu hash\uuuu()
方法。你可以检查一下

olddict = {"a":1, "b":{"test":"dict"}, "c":"string", "d":["list"] }

for key in olddict:
   if(olddict[key].__hash__):
      print str(olddict[key]) + " is hashable"
   else: 
      print str(olddict[key]) + " is NOT hashable"
输出

1 is hashable
string is hashable
{'test': 'dict'} is NOT hashable
['list'] is NOT hashable

为什么不用duck打字

for key in olddict:
   try:
       newdict[olddict[key]] = key
   except TypeError:
       newdict[str(olddict[key])] = key

我想最好的解决方案是使用集合。哈希:

import collections
if isinstance(olddict[key], collections.Hashable):
    newdict[olddict[key]] = key
else:
    newdict[str(olddict[key])] = key

内德——这正是我想要避免的。此外,此函数将捕获不是“不可损坏类型”的TypeErrors。hash()只会引发一个TypeError。或者,不管TypeError散列引发什么,它都会阻止您的值被散列。我甚至认为这应该捕获异常,因为hash()失败的原因并不重要:hash()中的失败会使您的值不可破坏。您能否进一步说明为什么要避免这样的异常?这将异常处理封装在一个很好的函数中,并使上面的示例代码能够完美地工作。也许这更像是一个哲学观点——问题不在于由于某种“反常条件”而无法修复的“异常条件”,而是关于类型上可用功能的查询。如果这有意义的话。我认为你是对的,这是一个哲学观点,也许可以归结为一个静态与动态的世界观。经典的Python思维模式通常会尝试一些事情并捕获异常,而不是试图预先确定某些理论上是可能的。@Paul Nathan:这是标准方法。简单地尝试操作;如果失败,则该对象不可散列;做点别的。如果它能工作,那么对象是可哈希的,并且您完成了预期的操作。关于这一点的警告:在Python 2.5中,这将给出:
{'test':'dict'}是可哈希的
。如果一个类定义了
\uuuuu hash\uuuuu
来引发类型错误,那么它也会在新版本中给出错误的结果。这也很糟糕。仅仅因为一个类型定义了一个
\uuuuu hash\uuuu()
方法,并不意味着该类型的所有可能实例都是可哈希的。考虑<代码> DEFH-HASHYZ(自):例如,提高ValueError(‘UHOH’)< /代码>。相反,唯一合理的解决方案是尝试
散列(olddict[key])
并报告
False
,如果这样做会引发任何异常。不,这是您只能在运行时确定的,因为在此之前列表的内容通常是未知的
hash([],)
给出
TypeError:unhabable类型:“list”
对使用Python 2.7的人的小警告
isinstance(bytearray([0xa]),collections.Hashable))
返回
True
hash(bytearray([0xa]))
失败,类型错误:不可损坏类型:“bytearray”。有人对此有任何解释吗
isinstance(Decimal('sNaN'),Hashable)
返回
True
但是当它被赋予字典时,我得到
无法对信号NaN值进行哈希处理
在Python3中它是
isinstance(obj,collections.abc.Hashable)
。在Python3.7.5中,直接从
集合导入会引发
弃用警告
。相反,
从collections.abc导入Hashable
for key in olddict:
   try:
       newdict[olddict[key]] = key
   except TypeError:
       newdict[str(olddict[key])] = key
import collections
if isinstance(olddict[key], collections.Hashable):
    newdict[olddict[key]] = key
else:
    newdict[str(olddict[key])] = key