2

I started with 2 different ways to make a key-value-reversed dictionary from a known dictionary. When I try to figure out whether these 2 are identical, I got this question. Here is my code.

a = {'a': 1, 'b': 2, 'c': 3}        # known dict
b = dict([(v, k) for k, v in a.items()])    # way # 1 to reverse
c = {v: k for k, v in a.items()}            # way # 2 to reverse

print(b.values())                   # returns dict_values(['a', 'b', 'c'])
print(c.values())                   # returns dict_values(['a', 'b', 'c'])
print(b.values() == c.values())     # returns False
print(b.keys())                     # returns dict_keys([1, 2, 3])
print(c.keys())                     # returns dict_keys([1, 2, 3])
print(b.keys() == c.keys())         # returns True
print(b == c)                       # returns True

I know that both dict.values() and dict.keys() returns a dictionary_view. What is this dictionary_view? Why b.values() and c.values() seem to be identical while they are not but b.keys() equal to c.keys()?

I also tries this code.

import types
print(isinstance(b.values(), types.GeneratorType))

And it returns False.

NNnOoB
  • 39
  • 3
  • 2
    `b` and `c` were each assigned from expressions that explicitly create a new object; they therefore definitely do not refer to the same object. It is *utterly inconceivable* that `b is c` could be true - that operator cares only about object identity, it knows nothing about equality. (I have no explanation for the inconsistency you're seeing between key and value views, so I'm not making a full answer out of this. If they both had failed to compare as equal, I would have said that's because these views are intended primarily for iteration, not any other operations.) – jasonharper Jun 01 '19 at 04:13
  • By the way, the behavior of `a.values() == b.values()` are inconsistent between python2 and python3. I've already submitted a bug here: https://bugs.python.org/issue37119 – johnlinp Jun 01 '19 at 04:25
  • @johnlinp Its because `.values()` isn't actually returning a list. It is returning a generator. Thus the OP is comparing two generators (which are can compare as equal or not equal). `print()` turns the generators into lists. Force the generators to complete and you get the desired result `print(set(b.values()) == set(c.values()))`. In python2 `.values()` does not return a generator which is why 2 and 3 is different. Btw `.keys()` is the same way, its a generator. I.e. its not a bug. Its a implementation detail of Python3. (though they could probably make it act different). – Error - Syntactical Remorse Jun 01 '19 at 04:38
  • https://docs.python.org/3/library/stdtypes.html#dict-views – wwii Jun 01 '19 at 04:44
  • @Error-SyntacticalRemorse Thank you for the reply. If `.values()` returns a generator, does `.keys()` also return a generator? If yes, why does `b.keys() == c.keys()` evaluate to `true`? – johnlinp Jun 01 '19 at 04:45
  • 2
    Possible duplicate of [When to use == and when to use is?](https://stackoverflow.com/questions/6570371/when-to-use-and-when-to-use-is) ... and [Is there a difference between “==” and “is”?](https://stackoverflow.com/questions/132988/is-there-a-difference-between-and-is) – wwii Jun 01 '19 at 04:50
  • @johnlinp Good question and I was slightly wrong. From the source code of python: "D.keys() -> a set-like object providing a view on D's keys");" so `keys` is a `set` but `values` is an object (generator): "D.values() -> an object providing a view on D's values");" thus the discrepancy. Probably implemented that way because the keys are always part of the object as a `set` but the only way to get `values` is go through each key and get it. – Error - Syntactical Remorse Jun 01 '19 at 04:52
  • @Error-SyntacticalRemorse Actually I don't think dict.values() return a generator object. As I did this code print(isinstance(b.values(), types.GeneratorType)) and this prints false. – NNnOoB Jun 02 '19 at 02:20
  • For the reason why b.values() != c.values(), you can see https://bugs.python.org/issue12445. The feature was requested, but rejected by the Python maintainer. – johnlinp Jun 03 '19 at 04:05

0 Answers0