字典成员资格的意外行为检查

时间:2018-01-25 13:31:12

标签: python dictionary

无法将不可用的对象插入到dict中。据记载,这是有充分理由的。

但是,我不明白它为什么会影响会员资格测试:

if value not in somedict:
    print("not present")

我假设会员资格测试只能返回TrueFalse。但是当value不可用时,它会失败TypeError: unhashable type。我会说True应该是此not in测试的正确答案,因为value显然未包含在somedict中,并且无法插入它完全无关紧要。

另一个例子:

try:
    result = somedict[value]
except KeyError:
    # handle the missing key

当值不可删除时,它会因TypeError: unhashable type而失败,我希望KeyError代替。

此外:

somedict.get(value, default)

不会返回默认值,但会抛出TypeError

那么为什么unhashable in somedict不会评估为False以及正确的测试只返回True或False?

更新

  

object.__contains__(self, item)

     

被调用以实现成员资格测试运营商。如果item是self,则返回true,否则返回false。

(来自"数据模型 - Python文档")

附录:

这是用户界面程序的简化部分,当其中一个参数是dict时失败。

# args = list of function arguments created from user's input
# where "V1" stands for value1 and "V2" stands for value2
XLAT = {'V1': value1, 'V2': value2} 
args = [XLAT.get(a, a) for a in args]
function(*args)

5 个答案:

答案 0 :(得分:9)

原因是通过生成潜在密钥的哈希值来完成对作为字典的一部分的潜在密钥的测试。如果潜在密钥无法提供哈希值(如果对象不可哈希),则无法进行测试。

在某种程度上,你是对的,在这种情况下,存在测试只能说“不,不存在”(“因为无论如何都不能插入”)。

这不是以这种方式完成的,因为它可能会掩盖许多编程错误。

如果你干净地编程,你很可能永远不会检查一个不可用的对象,无论它是否在字典中。 I. e。它需要相当多的幻想来提出你真正想要的案例。 (但我不会说这完全是不可能的。)因为编程错误导致你意外地做某事的情况发生这种检查的情况量要大得多。因此异常表明您应该查看代码中的位置。

如果你知道自己在做什么(也许就是你的情况),你应该只是抓住这个错误:

try:
    if strange_maybe_unhashable_value in my_dict:
        print("Yes, it's in!")
    else:
        print("No, it's not in!")
except TypeError:
    print("No, it's not even hashable!")

如果您想将其与KeyError处理相结合:

try:
    result = somedict[value]
except (KeyError, TypeError):
    # handle the missing key

try:
    result = somedict[value]
except KeyError:
    # handle the missing key
except TypeError:
    # react on the thing being unhashable

提供另一个相当深奥的方面:

对象可能在某个时间可以清洗,而在另一个对象(可能更晚)不可用。这当然不应该是这种情况,但可能发生,例如, G。如果哈希值依赖于外部的东西。尽管有一些共同的假设,但是可以使用是不可变的(尽管通常依赖于另一个)。因此,对象可以在作为字典的一部分时进行更改,并且此可以更改其哈希值。虽然这本身就是一个错误并且会导致字典无法正常工作,但这也可能是一个设计理由,不是简单地说“不存在”或提出KeyError而是提高TypeError代替。

答案 1 :(得分:0)

也许你可以检查它是否可以清洗,如果是:尝试你的代码,如果不是:返回False。这不是你的'为什么'问题的答案,但至少我认为它会起作用。

答案 2 :(得分:0)

如果您正在尝试测试dict中可能不存在的密钥,则表示您尝试针对错误的变量进行测试时出现逻辑错误或可能是错字。如果它永远不是真的,你为什么要尝试测试;您可能希望在代码中解决该问题。

将这些视为可以真正帮助调试的两种不同情况对我来说是有道理的。如果你确实有一个案例,你可以混合使用hashable和unhashable类型,并且这显然不是错误的,那么你应该清楚说明:

try:
    if value not in somedict:
        ...
except TypeError:
    ...

答案 3 :(得分:0)

我认为这更像是一个实施决定。这是有道理的:不可用类型应该返回特定类型的错误。

想象一下,您实现了一个Counter类,其中包含一个只计算对象的Dictionary

cnt.Add(x) # adds one to the counter
cnt.Count(x) # returns the number of occurences of x as seen by cnt, 0 if x has never been seen beofreL.

你在一组对象上运行它,其中一个碰巧是不可用的,但你不知道它。然后,当你想看看这个对象的出现次数时,程序将返回0,这不是真的。

另一方面,当类型不可用时存在特定异常的事实让开发人员选择要实现的行为。如果这两种情况只有一个例外,那么你就没有这个选择。

答案 4 :(得分:-1)

将其用作:

if value not in somedict.values():
    print("not present")