Inconsistent behaviour between dict.values() and dict.keys() equality in Python 3.x and Python 2.7
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
add a comment |
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
This seems to be interesting as I just checkedid
of two values and they are same as well still==
is returningFalse
. 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 tod.values() == d.values()
is false.
– VPfB
14 hours ago
Good catch, I'll edit my question to be more general.
– thom747
14 hours ago
add a comment |
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
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
python python-3.x python-2.7
edited 13 hours ago
Idlehands
5,9301823
5,9301823
asked 14 hours ago
thom747thom747
1607
1607
This seems to be interesting as I just checkedid
of two values and they are same as well still==
is returningFalse
. 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 tod.values() == d.values()
is false.
– VPfB
14 hours ago
Good catch, I'll edit my question to be more general.
– thom747
14 hours ago
add a comment |
This seems to be interesting as I just checkedid
of two values and they are same as well still==
is returningFalse
. 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 tod.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
add a comment |
1 Answer
1
active
oldest
votes
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
classcollections.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
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
add a comment |
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
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
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
classcollections.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
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
add a comment |
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
classcollections.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
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
add a comment |
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
classcollections.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
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
classcollections.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
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
add a comment |
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
add a comment |
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.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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
This seems to be interesting as I just checked
id
of two values and they are same as well still==
is returningFalse
. 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