[Python] Custom type object tests as member of sequence but not of dictionary

Discussão em 'Python' iniciado por Stack, Julho 7, 2025.

  1. Stack

    Stack Membro Participativo

    As per the official Python docs for in operator:


    For container types such as list, tuple, set, frozenset, dict, or collections.deque, the expression x in y is equivalent to any(x is e or x == e for e in y).
    ​

    However this does not seem to be true. Please see the following code:

    class Val:
    def __init__(self, val):
    self.val = val
    def __eq__(self, other):
    return self.val == other.val
    __hash__ = object.__hash__

    one = Val(1) ; two = Val(2) ; three = Val(3)

    valSeq = [one, two, three]

    print("Val(2) in valSeq:\n ", Val(2) in valSeq)


    This prints:

    Val(2) in valSeq:
    True


    as expected, but the same does not work when I use Val as a key in a dictionary:

    valMap = {one: "ekam", two: "dve", three: "trini"}

    print("valMap[Val(2)]:")
    try:
    print(valMap[Val(2)])
    except KeyError:
    print(" KeyError")

    print()

    print("Val(2) in valMap:\n ", Val(2) in valMap)


    This outputs:

    valMap[Val(2)]:
    KeyError

    Val(2) in valMap:
    False


    To investigate why this happens, I try testing what the documentation says:

    def inTest(obj, seq):
    return any(obj is test or obj == test for test in seq)
    print("inTest(Val(2), valMap):\n ", inTest(Val(2), valMap))


    which gives:

    inTest(Val(2), valMap):
    True


    and sure enough, the equality test of Val(2) is satisfied as expected:

    def inTestStr(obj, seq):
    for test in seq:
    print(obj is test, obj == test)
    print("inTestStr(Val(2), valMap):")
    inTestStr(Val(2), valMap)


    which gives:

    inTestStr(Val(2), valMap):
    False False
    False True
    False False


    What is wrong and why doesn't in operator work as expected?

    Continue reading...

Compartilhe esta Página