Python:`键不在my_dict`中,而是键在my_dict.keys()中

Ram*_*hum 4 python hash dictionary

我有一个奇怪的情况.我有一个词典,self.containing_dict.使用调试探针,我看到dict的内容,我可以看到它self是它的关键.但看看这个:

>>> self in self.containing_dict
False
>>> self in self.containing_dict.keys()
True
>>> self.containing_dict.has_key(self)
False
Run Code Online (Sandbox Code Playgroud)

这是怎么回事?

(我会注意到这是在一段代码中,它会在weakref回调中执行.)

更新:我被要求显示__hash__实施self.这里是:

def __hash__(self):
    return hash(
        (
            tuple(sorted(tuple(self.args))),
            self.star_args,
            tuple(sorted(tuple(self.star_kwargs)))
        )
    )

args = property(lambda self: dict(self.args_refs))

star_args = property(
    lambda self:
        tuple((star_arg_ref() for star_arg_ref in self.star_args_refs))
)

star_kwargs = property(lambda self: dict(self.star_kwargs_refs))    
Run Code Online (Sandbox Code Playgroud)

Tho*_*ers 5

您描述的问题只能由self实施__eq__(或__cmp__)而不实施附带的问题引起__hash__.如果你没有实现一个__hash__方法,你应该这样做 - 通常你不能使用定义__eq__但不能__hash__作为dict键的对象,但如果你继承了__hash__可能会滑过的对象.

如果你实现了__hash__,你必须确保它以正确的方式运行:结果不能在对象的生命周期内改变(或者至少只要对象被用作dict键或set item),并且它必须符合__eq__.对象的散列值必须与它等于的对象相同(根据它的__eq____cmp__.)对象的散列值可能与它不等于的对象不同,但它不一定是.这些要求也意味着您无法__eq__在对象的生命周期内获得更改结果,这就是为什么可变对象通常不能用作dict键的原因.

如果你__hash__和你__eq__没有匹配,那么Python将无法在dicts和sets中找到对象,但它仍将显示在,dict.keys()并且list(set),这就是你在这里描述的内容.实现__hash__方法的常用方法是返回hash()__eq____cmp__方法中使用的任何属性.