Inconsistent behaviour between dict.values() and dict.keys() equality in Python 3.x and Python 2.7












21















I have found that comparing the results of the keys() and values() methods of the dict built-in to themselves results in inconsistent results:



instance = {'one': 1}

instance.values() == instance.values() # Returns False
instance.keys() == instance.keys() # Returns True


Running the above code in Python 2.7 will return True for both calls, leading me to believe that there is some implementation detail in Python 3's dict_values that causes this strange behaviour.



Is there a reason for this behaviour or have i stumbled upon some obscure bug?










share|improve this question

























  • This seems to be interesting as I just checked id of two values and they are same as well still == is returning False. I believe one has to dig a bit more in the source code to find the reason for it.

    – mad_
    14 hours ago






  • 3





    Don't know the answer, but it can be simplified to d.values() == d.values() is false.

    – VPfB
    14 hours ago











  • Good catch, I'll edit my question to be more general.

    – thom747
    14 hours ago
















21















I have found that comparing the results of the keys() and values() methods of the dict built-in to themselves results in inconsistent results:



instance = {'one': 1}

instance.values() == instance.values() # Returns False
instance.keys() == instance.keys() # Returns True


Running the above code in Python 2.7 will return True for both calls, leading me to believe that there is some implementation detail in Python 3's dict_values that causes this strange behaviour.



Is there a reason for this behaviour or have i stumbled upon some obscure bug?










share|improve this question

























  • This seems to be interesting as I just checked id of two values and they are same as well still == is returning False. I believe one has to dig a bit more in the source code to find the reason for it.

    – mad_
    14 hours ago






  • 3





    Don't know the answer, but it can be simplified to d.values() == d.values() is false.

    – VPfB
    14 hours ago











  • Good catch, I'll edit my question to be more general.

    – thom747
    14 hours ago














21












21








21


1






I have found that comparing the results of the keys() and values() methods of the dict built-in to themselves results in inconsistent results:



instance = {'one': 1}

instance.values() == instance.values() # Returns False
instance.keys() == instance.keys() # Returns True


Running the above code in Python 2.7 will return True for both calls, leading me to believe that there is some implementation detail in Python 3's dict_values that causes this strange behaviour.



Is there a reason for this behaviour or have i stumbled upon some obscure bug?










share|improve this question
















I have found that comparing the results of the keys() and values() methods of the dict built-in to themselves results in inconsistent results:



instance = {'one': 1}

instance.values() == instance.values() # Returns False
instance.keys() == instance.keys() # Returns True


Running the above code in Python 2.7 will return True for both calls, leading me to believe that there is some implementation detail in Python 3's dict_values that causes this strange behaviour.



Is there a reason for this behaviour or have i stumbled upon some obscure bug?







python python-3.x python-2.7






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited 13 hours ago









Idlehands

5,9301823




5,9301823










asked 14 hours ago









thom747thom747

1607




1607













  • This seems to be interesting as I just checked id of two values and they are same as well still == is returning False. I believe one has to dig a bit more in the source code to find the reason for it.

    – mad_
    14 hours ago






  • 3





    Don't know the answer, but it can be simplified to d.values() == d.values() is false.

    – VPfB
    14 hours ago











  • Good catch, I'll edit my question to be more general.

    – thom747
    14 hours ago



















  • This seems to be interesting as I just checked id of two values and they are same as well still == is returning False. I believe one has to dig a bit more in the source code to find the reason for it.

    – mad_
    14 hours ago






  • 3





    Don't know the answer, but it can be simplified to d.values() == d.values() is false.

    – VPfB
    14 hours ago











  • Good catch, I'll edit my question to be more general.

    – thom747
    14 hours ago

















This seems to be interesting as I just checked id of two values and they are same as well still == is returning False. I believe one has to dig a bit more in the source code to find the reason for it.

– mad_
14 hours ago





This seems to be interesting as I just checked id of two values and they are same as well still == is returning False. I believe one has to dig a bit more in the source code to find the reason for it.

– mad_
14 hours ago




3




3





Don't know the answer, but it can be simplified to d.values() == d.values() is false.

– VPfB
14 hours ago





Don't know the answer, but it can be simplified to d.values() == d.values() is false.

– VPfB
14 hours ago













Good catch, I'll edit my question to be more general.

– thom747
14 hours ago





Good catch, I'll edit my question to be more general.

– thom747
14 hours ago












1 Answer
1






active

oldest

votes


















27














The short answer: class dict_values doesn't have a __eq__ method implemented, but class dict_keys does:



>>> d.values().__eq__(d.values())
NotImplemented
>>> d.keys().__eq__(d.keys())
True


Therefore, the d.values()'s == comparison evaluates to False.



The longer answer of why it wasn't implemented is a different one and can be seen with a little more digging on the documentation of dict-view objects. This part seems especially relevant (emphasis mine):




Keys views are set-like since their entries are unique and hashable.
If all values are hashable, so that (key, value) pairs are unique and
hashable, then the items view is also set-like. (Values views are not
treated as set-like since the entries are generally not unique.) For
set-like views, all of the operations defined for the abstract base
class collections.abc.Set are available (for example, ==, <, or ^).




Since keys must be unique, it makes sense that they are set-like and are supported with the class operations of collections.Set. Values are not set-like due to non-uniqueness.



In Python 2.7 however, d.keys() and d.values() both return a list per the documentation therefore this restriction does not apply. Since they are both the same type of object, it makes sense the same operation will work on both. If you used viewkeys and viewvalues as mentioned in the documentation of dict-view objects in Python2.7, then you can expect similar behaviour:



# Python 2.7
from collections import Set
# in Python 3.x this would be from collections.abc import Set

d = {"one": 1}

print isinstance(d.viewkeys(), Set)
# True

print isinstance(d.viewvalues(), Set)
# False

print d.viewkeys() == d.viewkeys()
# True

print d.viewvalues() == d.viewvalues()
# False





share|improve this answer


























  • OP: I updated the answer with more info on why Python2.7 behaves differently since you accepted. Please check back if you have time.

    – Idlehands
    13 hours ago











Your Answer






StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














draft saved

draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55026840%2finconsistent-behaviour-between-dict-values-and-dict-keys-equality-in-python%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes









27














The short answer: class dict_values doesn't have a __eq__ method implemented, but class dict_keys does:



>>> d.values().__eq__(d.values())
NotImplemented
>>> d.keys().__eq__(d.keys())
True


Therefore, the d.values()'s == comparison evaluates to False.



The longer answer of why it wasn't implemented is a different one and can be seen with a little more digging on the documentation of dict-view objects. This part seems especially relevant (emphasis mine):




Keys views are set-like since their entries are unique and hashable.
If all values are hashable, so that (key, value) pairs are unique and
hashable, then the items view is also set-like. (Values views are not
treated as set-like since the entries are generally not unique.) For
set-like views, all of the operations defined for the abstract base
class collections.abc.Set are available (for example, ==, <, or ^).




Since keys must be unique, it makes sense that they are set-like and are supported with the class operations of collections.Set. Values are not set-like due to non-uniqueness.



In Python 2.7 however, d.keys() and d.values() both return a list per the documentation therefore this restriction does not apply. Since they are both the same type of object, it makes sense the same operation will work on both. If you used viewkeys and viewvalues as mentioned in the documentation of dict-view objects in Python2.7, then you can expect similar behaviour:



# Python 2.7
from collections import Set
# in Python 3.x this would be from collections.abc import Set

d = {"one": 1}

print isinstance(d.viewkeys(), Set)
# True

print isinstance(d.viewvalues(), Set)
# False

print d.viewkeys() == d.viewkeys()
# True

print d.viewvalues() == d.viewvalues()
# False





share|improve this answer


























  • OP: I updated the answer with more info on why Python2.7 behaves differently since you accepted. Please check back if you have time.

    – Idlehands
    13 hours ago
















27














The short answer: class dict_values doesn't have a __eq__ method implemented, but class dict_keys does:



>>> d.values().__eq__(d.values())
NotImplemented
>>> d.keys().__eq__(d.keys())
True


Therefore, the d.values()'s == comparison evaluates to False.



The longer answer of why it wasn't implemented is a different one and can be seen with a little more digging on the documentation of dict-view objects. This part seems especially relevant (emphasis mine):




Keys views are set-like since their entries are unique and hashable.
If all values are hashable, so that (key, value) pairs are unique and
hashable, then the items view is also set-like. (Values views are not
treated as set-like since the entries are generally not unique.) For
set-like views, all of the operations defined for the abstract base
class collections.abc.Set are available (for example, ==, <, or ^).




Since keys must be unique, it makes sense that they are set-like and are supported with the class operations of collections.Set. Values are not set-like due to non-uniqueness.



In Python 2.7 however, d.keys() and d.values() both return a list per the documentation therefore this restriction does not apply. Since they are both the same type of object, it makes sense the same operation will work on both. If you used viewkeys and viewvalues as mentioned in the documentation of dict-view objects in Python2.7, then you can expect similar behaviour:



# Python 2.7
from collections import Set
# in Python 3.x this would be from collections.abc import Set

d = {"one": 1}

print isinstance(d.viewkeys(), Set)
# True

print isinstance(d.viewvalues(), Set)
# False

print d.viewkeys() == d.viewkeys()
# True

print d.viewvalues() == d.viewvalues()
# False





share|improve this answer


























  • OP: I updated the answer with more info on why Python2.7 behaves differently since you accepted. Please check back if you have time.

    – Idlehands
    13 hours ago














27












27








27







The short answer: class dict_values doesn't have a __eq__ method implemented, but class dict_keys does:



>>> d.values().__eq__(d.values())
NotImplemented
>>> d.keys().__eq__(d.keys())
True


Therefore, the d.values()'s == comparison evaluates to False.



The longer answer of why it wasn't implemented is a different one and can be seen with a little more digging on the documentation of dict-view objects. This part seems especially relevant (emphasis mine):




Keys views are set-like since their entries are unique and hashable.
If all values are hashable, so that (key, value) pairs are unique and
hashable, then the items view is also set-like. (Values views are not
treated as set-like since the entries are generally not unique.) For
set-like views, all of the operations defined for the abstract base
class collections.abc.Set are available (for example, ==, <, or ^).




Since keys must be unique, it makes sense that they are set-like and are supported with the class operations of collections.Set. Values are not set-like due to non-uniqueness.



In Python 2.7 however, d.keys() and d.values() both return a list per the documentation therefore this restriction does not apply. Since they are both the same type of object, it makes sense the same operation will work on both. If you used viewkeys and viewvalues as mentioned in the documentation of dict-view objects in Python2.7, then you can expect similar behaviour:



# Python 2.7
from collections import Set
# in Python 3.x this would be from collections.abc import Set

d = {"one": 1}

print isinstance(d.viewkeys(), Set)
# True

print isinstance(d.viewvalues(), Set)
# False

print d.viewkeys() == d.viewkeys()
# True

print d.viewvalues() == d.viewvalues()
# False





share|improve this answer















The short answer: class dict_values doesn't have a __eq__ method implemented, but class dict_keys does:



>>> d.values().__eq__(d.values())
NotImplemented
>>> d.keys().__eq__(d.keys())
True


Therefore, the d.values()'s == comparison evaluates to False.



The longer answer of why it wasn't implemented is a different one and can be seen with a little more digging on the documentation of dict-view objects. This part seems especially relevant (emphasis mine):




Keys views are set-like since their entries are unique and hashable.
If all values are hashable, so that (key, value) pairs are unique and
hashable, then the items view is also set-like. (Values views are not
treated as set-like since the entries are generally not unique.) For
set-like views, all of the operations defined for the abstract base
class collections.abc.Set are available (for example, ==, <, or ^).




Since keys must be unique, it makes sense that they are set-like and are supported with the class operations of collections.Set. Values are not set-like due to non-uniqueness.



In Python 2.7 however, d.keys() and d.values() both return a list per the documentation therefore this restriction does not apply. Since they are both the same type of object, it makes sense the same operation will work on both. If you used viewkeys and viewvalues as mentioned in the documentation of dict-view objects in Python2.7, then you can expect similar behaviour:



# Python 2.7
from collections import Set
# in Python 3.x this would be from collections.abc import Set

d = {"one": 1}

print isinstance(d.viewkeys(), Set)
# True

print isinstance(d.viewvalues(), Set)
# False

print d.viewkeys() == d.viewkeys()
# True

print d.viewvalues() == d.viewvalues()
# False






share|improve this answer














share|improve this answer



share|improve this answer








edited 13 hours ago

























answered 14 hours ago









IdlehandsIdlehands

5,9301823




5,9301823













  • OP: I updated the answer with more info on why Python2.7 behaves differently since you accepted. Please check back if you have time.

    – Idlehands
    13 hours ago



















  • OP: I updated the answer with more info on why Python2.7 behaves differently since you accepted. Please check back if you have time.

    – Idlehands
    13 hours ago

















OP: I updated the answer with more info on why Python2.7 behaves differently since you accepted. Please check back if you have time.

– Idlehands
13 hours ago





OP: I updated the answer with more info on why Python2.7 behaves differently since you accepted. Please check back if you have time.

– Idlehands
13 hours ago




















draft saved

draft discarded




















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55026840%2finconsistent-behaviour-between-dict-values-and-dict-keys-equality-in-python%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

"Incorrect syntax near the keyword 'ON'. (on update cascade, on delete cascade,)

Alcedinidae

Origin of the phrase “under your belt”?