Why does `if None.__eq__(“a”)` evaluate to True?
If you execute the following statement in Python 3.7, it will (from my testing) print b
:
if None.__eq__("a"):
print("b")
However, None.__eq__("a")
evaluates to NotImplemented
.
Naturally, "a".__eq__("a")
evaluates to True
, and "b".__eq__("a")
evaluates to False
.
I initially discovered this when testing the return value of a function, but didn't return anything in the second case -- so, the function returned None
.
What's going on here?
python python-3.x string equivalence
This question has an open bounty worth +50
reputation from vaultah ending in 7 days.
This question has not received enough attention.
add a comment |
If you execute the following statement in Python 3.7, it will (from my testing) print b
:
if None.__eq__("a"):
print("b")
However, None.__eq__("a")
evaluates to NotImplemented
.
Naturally, "a".__eq__("a")
evaluates to True
, and "b".__eq__("a")
evaluates to False
.
I initially discovered this when testing the return value of a function, but didn't return anything in the second case -- so, the function returned None
.
What's going on here?
python python-3.x string equivalence
This question has an open bounty worth +50
reputation from vaultah ending in 7 days.
This question has not received enough attention.
The title was wrong. The result is notTrue
, as you noted yourself. It is a "truthy value", i.e. a valuex
such thatbool(x) is True
.
– Bakuriu
yesterday
The title is fine. if [truthy value] evaluates to true.
– coldspeed
yesterday
add a comment |
If you execute the following statement in Python 3.7, it will (from my testing) print b
:
if None.__eq__("a"):
print("b")
However, None.__eq__("a")
evaluates to NotImplemented
.
Naturally, "a".__eq__("a")
evaluates to True
, and "b".__eq__("a")
evaluates to False
.
I initially discovered this when testing the return value of a function, but didn't return anything in the second case -- so, the function returned None
.
What's going on here?
python python-3.x string equivalence
If you execute the following statement in Python 3.7, it will (from my testing) print b
:
if None.__eq__("a"):
print("b")
However, None.__eq__("a")
evaluates to NotImplemented
.
Naturally, "a".__eq__("a")
evaluates to True
, and "b".__eq__("a")
evaluates to False
.
I initially discovered this when testing the return value of a function, but didn't return anything in the second case -- so, the function returned None
.
What's going on here?
python python-3.x string equivalence
python python-3.x string equivalence
edited yesterday
coldspeed
120k21120202
120k21120202
asked Dec 31 '18 at 6:03
The AI Architect
5671716
5671716
This question has an open bounty worth +50
reputation from vaultah ending in 7 days.
This question has not received enough attention.
This question has an open bounty worth +50
reputation from vaultah ending in 7 days.
This question has not received enough attention.
The title was wrong. The result is notTrue
, as you noted yourself. It is a "truthy value", i.e. a valuex
such thatbool(x) is True
.
– Bakuriu
yesterday
The title is fine. if [truthy value] evaluates to true.
– coldspeed
yesterday
add a comment |
The title was wrong. The result is notTrue
, as you noted yourself. It is a "truthy value", i.e. a valuex
such thatbool(x) is True
.
– Bakuriu
yesterday
The title is fine. if [truthy value] evaluates to true.
– coldspeed
yesterday
The title was wrong. The result is not
True
, as you noted yourself. It is a "truthy value", i.e. a value x
such that bool(x) is True
.– Bakuriu
yesterday
The title was wrong. The result is not
True
, as you noted yourself. It is a "truthy value", i.e. a value x
such that bool(x) is True
.– Bakuriu
yesterday
The title is fine. if [truthy value] evaluates to true.
– coldspeed
yesterday
The title is fine. if [truthy value] evaluates to true.
– coldspeed
yesterday
add a comment |
3 Answers
3
active
oldest
votes
This is a great example of why the __dunder__
methods should not be used directly as they are quite often not appropriate replacements for their equivalent operators; you should use the ==
operator instead for equality comparisons, or in this special case, when checking for None
, use is
(skip to the bottom of the answer for more information).
You've done
None.__eq__('a')
# NotImplemented
Which returns NotImplemented
since the types being compared are different. Consider another example where two objects with different types are being compared in this fashion, such as 1
and 'a'
. Doing (1).__eq__('a')
is also not correct, and will return NotImplemented
. The right way to compare these two values for equality would be
1 == 'a'
# False
What happens here is
- First,
(1).__eq__('a')
is tried, which returnsNotImplemented
. This indicates that the operation is not supported, so
'a'.__eq__(1)
is called, which also returns the sameNotImplemented
. So,- The objects are treated as if they are not the same, and
False
is returned.
Here's a nice little MCVE using some custom classes to illustrate how this happens:
class A:
def __eq__(self, other):
print('A.__eq__')
return NotImplemented
class B:
def __eq__(self, other):
print('B.__eq__')
return NotImplemented
class C:
def __eq__(self, other):
print('C.__eq__')
return True
a = A()
b = B()
c = C()
print(a == b)
# A.__eq__
# B.__eq__
# False
print(a == c)
# A.__eq__
# C.__eq__
# True
print(c == a)
# C.__eq__
# True
Of course, that doesn't explain why the operation returns true. This is because NotImplemented
is actually a truthy value:
bool(None.__eq__("a"))
# True
Same as,
bool(NotImplemented)
# True
For more information on what values are considered truthy and falsey, see the docs section on Truth Value Testing, as well as this answer. It is worth noting here that NotImplemented
is truthy, but it would have been a different story had the class defined a __bool__
or __len__
method that returned False
or 0
respectively.
If you want the functional equivalent of the ==
operator, use operator.eq
:
import operator
operator.eq(1, 'a')
# False
However, as mentioned earlier, for this specific scenario, where you are checking for None
, use is
:
var = 'a'
var is None
# False
var2 = None
var2 is None
# True
The functional equivalent of this is using operator.is_
:
operator.is_(var2, None)
# True
None
is a special object, and only 1 version exists in memory at any point of time. IOW, it is the sole singleton of the NoneType
class (but the same object may have any number of references). The PEP8 guidelines make this explicit:
Comparisons to singletons like
None
should always be done withis
or
is not
, never the equality operators.
In summary, for singletons like None
, a reference check with is
is more appropriate, although both ==
and is
will work just fine.
4
Nevertheless, I think it'd be worthy to note thatNone
should be checked withis None
, not==
,operator.eq
or.__eq__
– DeepSpace
Dec 31 '18 at 11:58
3
@DeepSpace Thanks for that, I have reworked the answer so as to explain why==
is better in any general situation, and whyis
is more appropriate for this specific one, quoting PEP8 at the bottom. Thanks for the comment!
– coldspeed
Dec 31 '18 at 12:12
It's worth mentioning (since it wasn't obvious to me) thatNotImplemented
belongs to the class<class 'NotImplementedType'>
. Here,bool(NotImplemented)
evaluates toTrue
, because of some combination of:__bool__
undefined (most likely) /__bool__
explicitly defined to beTue
/__len__
doesn't give0
.
– jpp
Dec 31 '18 at 13:29
@jpp I don't think that class defines either__bool__
or__len__
. I believe the spec dictates that the object is truthy unless__bool__
or__len__
say otherwise. You can read more here (that link is also included in the answer :-)).
– coldspeed
Dec 31 '18 at 14:51
1
@coldspeed, Yup, I thought so. But it's worth clarification because new users may fall into the trap that'a' == 'NotImplemented'
should returnFalse
! While the underlying reason is you aren't working with strings but aNotImplementedType
object.
– jpp
Dec 31 '18 at 14:54
|
show 1 more comment
The result you are seeing is caused by
None.__eq__("a") # evaluates to NotImplemented
and NotImplemented
's truth value is documented to be True
:
https://docs.python.org/3/library/constants.html
Special value which should be returned by the binary special methods (e.g. eq(), lt(), add(), rsub(), etc.) to indicate that the operation is not implemented with respect to the other type; may be returned by the in-place binary special methods (e.g. imul(), iand(), etc.) for the same purpose. Its truth value is true.
If you call the __eq()__
method manually rather than just using ==
, you need to be prepared to deal with the possibility it may return NotImplemented
and that its truth value is true.
add a comment |
As you already figured None.__eq__("a")
evaluates to NotImplemented
however if you try something like
if NotImplemented:
print("Yes")
else:
print("No")
the result is
yes
this mean that the truth value of NotImplemented
true
Therefor the outcome of the question is obvious:
None.__eq__(something)
yields NotImplemented
And bool(NotImplemented)
evaluates to True
So if None.__eq__("a")
is always True
New contributor
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%2f53984116%2fwhy-does-if-none-eq-a-evaluate-to-true%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
3 Answers
3
active
oldest
votes
3 Answers
3
active
oldest
votes
active
oldest
votes
active
oldest
votes
This is a great example of why the __dunder__
methods should not be used directly as they are quite often not appropriate replacements for their equivalent operators; you should use the ==
operator instead for equality comparisons, or in this special case, when checking for None
, use is
(skip to the bottom of the answer for more information).
You've done
None.__eq__('a')
# NotImplemented
Which returns NotImplemented
since the types being compared are different. Consider another example where two objects with different types are being compared in this fashion, such as 1
and 'a'
. Doing (1).__eq__('a')
is also not correct, and will return NotImplemented
. The right way to compare these two values for equality would be
1 == 'a'
# False
What happens here is
- First,
(1).__eq__('a')
is tried, which returnsNotImplemented
. This indicates that the operation is not supported, so
'a'.__eq__(1)
is called, which also returns the sameNotImplemented
. So,- The objects are treated as if they are not the same, and
False
is returned.
Here's a nice little MCVE using some custom classes to illustrate how this happens:
class A:
def __eq__(self, other):
print('A.__eq__')
return NotImplemented
class B:
def __eq__(self, other):
print('B.__eq__')
return NotImplemented
class C:
def __eq__(self, other):
print('C.__eq__')
return True
a = A()
b = B()
c = C()
print(a == b)
# A.__eq__
# B.__eq__
# False
print(a == c)
# A.__eq__
# C.__eq__
# True
print(c == a)
# C.__eq__
# True
Of course, that doesn't explain why the operation returns true. This is because NotImplemented
is actually a truthy value:
bool(None.__eq__("a"))
# True
Same as,
bool(NotImplemented)
# True
For more information on what values are considered truthy and falsey, see the docs section on Truth Value Testing, as well as this answer. It is worth noting here that NotImplemented
is truthy, but it would have been a different story had the class defined a __bool__
or __len__
method that returned False
or 0
respectively.
If you want the functional equivalent of the ==
operator, use operator.eq
:
import operator
operator.eq(1, 'a')
# False
However, as mentioned earlier, for this specific scenario, where you are checking for None
, use is
:
var = 'a'
var is None
# False
var2 = None
var2 is None
# True
The functional equivalent of this is using operator.is_
:
operator.is_(var2, None)
# True
None
is a special object, and only 1 version exists in memory at any point of time. IOW, it is the sole singleton of the NoneType
class (but the same object may have any number of references). The PEP8 guidelines make this explicit:
Comparisons to singletons like
None
should always be done withis
or
is not
, never the equality operators.
In summary, for singletons like None
, a reference check with is
is more appropriate, although both ==
and is
will work just fine.
4
Nevertheless, I think it'd be worthy to note thatNone
should be checked withis None
, not==
,operator.eq
or.__eq__
– DeepSpace
Dec 31 '18 at 11:58
3
@DeepSpace Thanks for that, I have reworked the answer so as to explain why==
is better in any general situation, and whyis
is more appropriate for this specific one, quoting PEP8 at the bottom. Thanks for the comment!
– coldspeed
Dec 31 '18 at 12:12
It's worth mentioning (since it wasn't obvious to me) thatNotImplemented
belongs to the class<class 'NotImplementedType'>
. Here,bool(NotImplemented)
evaluates toTrue
, because of some combination of:__bool__
undefined (most likely) /__bool__
explicitly defined to beTue
/__len__
doesn't give0
.
– jpp
Dec 31 '18 at 13:29
@jpp I don't think that class defines either__bool__
or__len__
. I believe the spec dictates that the object is truthy unless__bool__
or__len__
say otherwise. You can read more here (that link is also included in the answer :-)).
– coldspeed
Dec 31 '18 at 14:51
1
@coldspeed, Yup, I thought so. But it's worth clarification because new users may fall into the trap that'a' == 'NotImplemented'
should returnFalse
! While the underlying reason is you aren't working with strings but aNotImplementedType
object.
– jpp
Dec 31 '18 at 14:54
|
show 1 more comment
This is a great example of why the __dunder__
methods should not be used directly as they are quite often not appropriate replacements for their equivalent operators; you should use the ==
operator instead for equality comparisons, or in this special case, when checking for None
, use is
(skip to the bottom of the answer for more information).
You've done
None.__eq__('a')
# NotImplemented
Which returns NotImplemented
since the types being compared are different. Consider another example where two objects with different types are being compared in this fashion, such as 1
and 'a'
. Doing (1).__eq__('a')
is also not correct, and will return NotImplemented
. The right way to compare these two values for equality would be
1 == 'a'
# False
What happens here is
- First,
(1).__eq__('a')
is tried, which returnsNotImplemented
. This indicates that the operation is not supported, so
'a'.__eq__(1)
is called, which also returns the sameNotImplemented
. So,- The objects are treated as if they are not the same, and
False
is returned.
Here's a nice little MCVE using some custom classes to illustrate how this happens:
class A:
def __eq__(self, other):
print('A.__eq__')
return NotImplemented
class B:
def __eq__(self, other):
print('B.__eq__')
return NotImplemented
class C:
def __eq__(self, other):
print('C.__eq__')
return True
a = A()
b = B()
c = C()
print(a == b)
# A.__eq__
# B.__eq__
# False
print(a == c)
# A.__eq__
# C.__eq__
# True
print(c == a)
# C.__eq__
# True
Of course, that doesn't explain why the operation returns true. This is because NotImplemented
is actually a truthy value:
bool(None.__eq__("a"))
# True
Same as,
bool(NotImplemented)
# True
For more information on what values are considered truthy and falsey, see the docs section on Truth Value Testing, as well as this answer. It is worth noting here that NotImplemented
is truthy, but it would have been a different story had the class defined a __bool__
or __len__
method that returned False
or 0
respectively.
If you want the functional equivalent of the ==
operator, use operator.eq
:
import operator
operator.eq(1, 'a')
# False
However, as mentioned earlier, for this specific scenario, where you are checking for None
, use is
:
var = 'a'
var is None
# False
var2 = None
var2 is None
# True
The functional equivalent of this is using operator.is_
:
operator.is_(var2, None)
# True
None
is a special object, and only 1 version exists in memory at any point of time. IOW, it is the sole singleton of the NoneType
class (but the same object may have any number of references). The PEP8 guidelines make this explicit:
Comparisons to singletons like
None
should always be done withis
or
is not
, never the equality operators.
In summary, for singletons like None
, a reference check with is
is more appropriate, although both ==
and is
will work just fine.
4
Nevertheless, I think it'd be worthy to note thatNone
should be checked withis None
, not==
,operator.eq
or.__eq__
– DeepSpace
Dec 31 '18 at 11:58
3
@DeepSpace Thanks for that, I have reworked the answer so as to explain why==
is better in any general situation, and whyis
is more appropriate for this specific one, quoting PEP8 at the bottom. Thanks for the comment!
– coldspeed
Dec 31 '18 at 12:12
It's worth mentioning (since it wasn't obvious to me) thatNotImplemented
belongs to the class<class 'NotImplementedType'>
. Here,bool(NotImplemented)
evaluates toTrue
, because of some combination of:__bool__
undefined (most likely) /__bool__
explicitly defined to beTue
/__len__
doesn't give0
.
– jpp
Dec 31 '18 at 13:29
@jpp I don't think that class defines either__bool__
or__len__
. I believe the spec dictates that the object is truthy unless__bool__
or__len__
say otherwise. You can read more here (that link is also included in the answer :-)).
– coldspeed
Dec 31 '18 at 14:51
1
@coldspeed, Yup, I thought so. But it's worth clarification because new users may fall into the trap that'a' == 'NotImplemented'
should returnFalse
! While the underlying reason is you aren't working with strings but aNotImplementedType
object.
– jpp
Dec 31 '18 at 14:54
|
show 1 more comment
This is a great example of why the __dunder__
methods should not be used directly as they are quite often not appropriate replacements for their equivalent operators; you should use the ==
operator instead for equality comparisons, or in this special case, when checking for None
, use is
(skip to the bottom of the answer for more information).
You've done
None.__eq__('a')
# NotImplemented
Which returns NotImplemented
since the types being compared are different. Consider another example where two objects with different types are being compared in this fashion, such as 1
and 'a'
. Doing (1).__eq__('a')
is also not correct, and will return NotImplemented
. The right way to compare these two values for equality would be
1 == 'a'
# False
What happens here is
- First,
(1).__eq__('a')
is tried, which returnsNotImplemented
. This indicates that the operation is not supported, so
'a'.__eq__(1)
is called, which also returns the sameNotImplemented
. So,- The objects are treated as if they are not the same, and
False
is returned.
Here's a nice little MCVE using some custom classes to illustrate how this happens:
class A:
def __eq__(self, other):
print('A.__eq__')
return NotImplemented
class B:
def __eq__(self, other):
print('B.__eq__')
return NotImplemented
class C:
def __eq__(self, other):
print('C.__eq__')
return True
a = A()
b = B()
c = C()
print(a == b)
# A.__eq__
# B.__eq__
# False
print(a == c)
# A.__eq__
# C.__eq__
# True
print(c == a)
# C.__eq__
# True
Of course, that doesn't explain why the operation returns true. This is because NotImplemented
is actually a truthy value:
bool(None.__eq__("a"))
# True
Same as,
bool(NotImplemented)
# True
For more information on what values are considered truthy and falsey, see the docs section on Truth Value Testing, as well as this answer. It is worth noting here that NotImplemented
is truthy, but it would have been a different story had the class defined a __bool__
or __len__
method that returned False
or 0
respectively.
If you want the functional equivalent of the ==
operator, use operator.eq
:
import operator
operator.eq(1, 'a')
# False
However, as mentioned earlier, for this specific scenario, where you are checking for None
, use is
:
var = 'a'
var is None
# False
var2 = None
var2 is None
# True
The functional equivalent of this is using operator.is_
:
operator.is_(var2, None)
# True
None
is a special object, and only 1 version exists in memory at any point of time. IOW, it is the sole singleton of the NoneType
class (but the same object may have any number of references). The PEP8 guidelines make this explicit:
Comparisons to singletons like
None
should always be done withis
or
is not
, never the equality operators.
In summary, for singletons like None
, a reference check with is
is more appropriate, although both ==
and is
will work just fine.
This is a great example of why the __dunder__
methods should not be used directly as they are quite often not appropriate replacements for their equivalent operators; you should use the ==
operator instead for equality comparisons, or in this special case, when checking for None
, use is
(skip to the bottom of the answer for more information).
You've done
None.__eq__('a')
# NotImplemented
Which returns NotImplemented
since the types being compared are different. Consider another example where two objects with different types are being compared in this fashion, such as 1
and 'a'
. Doing (1).__eq__('a')
is also not correct, and will return NotImplemented
. The right way to compare these two values for equality would be
1 == 'a'
# False
What happens here is
- First,
(1).__eq__('a')
is tried, which returnsNotImplemented
. This indicates that the operation is not supported, so
'a'.__eq__(1)
is called, which also returns the sameNotImplemented
. So,- The objects are treated as if they are not the same, and
False
is returned.
Here's a nice little MCVE using some custom classes to illustrate how this happens:
class A:
def __eq__(self, other):
print('A.__eq__')
return NotImplemented
class B:
def __eq__(self, other):
print('B.__eq__')
return NotImplemented
class C:
def __eq__(self, other):
print('C.__eq__')
return True
a = A()
b = B()
c = C()
print(a == b)
# A.__eq__
# B.__eq__
# False
print(a == c)
# A.__eq__
# C.__eq__
# True
print(c == a)
# C.__eq__
# True
Of course, that doesn't explain why the operation returns true. This is because NotImplemented
is actually a truthy value:
bool(None.__eq__("a"))
# True
Same as,
bool(NotImplemented)
# True
For more information on what values are considered truthy and falsey, see the docs section on Truth Value Testing, as well as this answer. It is worth noting here that NotImplemented
is truthy, but it would have been a different story had the class defined a __bool__
or __len__
method that returned False
or 0
respectively.
If you want the functional equivalent of the ==
operator, use operator.eq
:
import operator
operator.eq(1, 'a')
# False
However, as mentioned earlier, for this specific scenario, where you are checking for None
, use is
:
var = 'a'
var is None
# False
var2 = None
var2 is None
# True
The functional equivalent of this is using operator.is_
:
operator.is_(var2, None)
# True
None
is a special object, and only 1 version exists in memory at any point of time. IOW, it is the sole singleton of the NoneType
class (but the same object may have any number of references). The PEP8 guidelines make this explicit:
Comparisons to singletons like
None
should always be done withis
or
is not
, never the equality operators.
In summary, for singletons like None
, a reference check with is
is more appropriate, although both ==
and is
will work just fine.
edited Dec 31 '18 at 15:04
answered Dec 31 '18 at 6:16
coldspeed
120k21120202
120k21120202
4
Nevertheless, I think it'd be worthy to note thatNone
should be checked withis None
, not==
,operator.eq
or.__eq__
– DeepSpace
Dec 31 '18 at 11:58
3
@DeepSpace Thanks for that, I have reworked the answer so as to explain why==
is better in any general situation, and whyis
is more appropriate for this specific one, quoting PEP8 at the bottom. Thanks for the comment!
– coldspeed
Dec 31 '18 at 12:12
It's worth mentioning (since it wasn't obvious to me) thatNotImplemented
belongs to the class<class 'NotImplementedType'>
. Here,bool(NotImplemented)
evaluates toTrue
, because of some combination of:__bool__
undefined (most likely) /__bool__
explicitly defined to beTue
/__len__
doesn't give0
.
– jpp
Dec 31 '18 at 13:29
@jpp I don't think that class defines either__bool__
or__len__
. I believe the spec dictates that the object is truthy unless__bool__
or__len__
say otherwise. You can read more here (that link is also included in the answer :-)).
– coldspeed
Dec 31 '18 at 14:51
1
@coldspeed, Yup, I thought so. But it's worth clarification because new users may fall into the trap that'a' == 'NotImplemented'
should returnFalse
! While the underlying reason is you aren't working with strings but aNotImplementedType
object.
– jpp
Dec 31 '18 at 14:54
|
show 1 more comment
4
Nevertheless, I think it'd be worthy to note thatNone
should be checked withis None
, not==
,operator.eq
or.__eq__
– DeepSpace
Dec 31 '18 at 11:58
3
@DeepSpace Thanks for that, I have reworked the answer so as to explain why==
is better in any general situation, and whyis
is more appropriate for this specific one, quoting PEP8 at the bottom. Thanks for the comment!
– coldspeed
Dec 31 '18 at 12:12
It's worth mentioning (since it wasn't obvious to me) thatNotImplemented
belongs to the class<class 'NotImplementedType'>
. Here,bool(NotImplemented)
evaluates toTrue
, because of some combination of:__bool__
undefined (most likely) /__bool__
explicitly defined to beTue
/__len__
doesn't give0
.
– jpp
Dec 31 '18 at 13:29
@jpp I don't think that class defines either__bool__
or__len__
. I believe the spec dictates that the object is truthy unless__bool__
or__len__
say otherwise. You can read more here (that link is also included in the answer :-)).
– coldspeed
Dec 31 '18 at 14:51
1
@coldspeed, Yup, I thought so. But it's worth clarification because new users may fall into the trap that'a' == 'NotImplemented'
should returnFalse
! While the underlying reason is you aren't working with strings but aNotImplementedType
object.
– jpp
Dec 31 '18 at 14:54
4
4
Nevertheless, I think it'd be worthy to note that
None
should be checked with is None
, not ==
, operator.eq
or .__eq__
– DeepSpace
Dec 31 '18 at 11:58
Nevertheless, I think it'd be worthy to note that
None
should be checked with is None
, not ==
, operator.eq
or .__eq__
– DeepSpace
Dec 31 '18 at 11:58
3
3
@DeepSpace Thanks for that, I have reworked the answer so as to explain why
==
is better in any general situation, and why is
is more appropriate for this specific one, quoting PEP8 at the bottom. Thanks for the comment!– coldspeed
Dec 31 '18 at 12:12
@DeepSpace Thanks for that, I have reworked the answer so as to explain why
==
is better in any general situation, and why is
is more appropriate for this specific one, quoting PEP8 at the bottom. Thanks for the comment!– coldspeed
Dec 31 '18 at 12:12
It's worth mentioning (since it wasn't obvious to me) that
NotImplemented
belongs to the class <class 'NotImplementedType'>
. Here, bool(NotImplemented)
evaluates to True
, because of some combination of: __bool__
undefined (most likely) / __bool__
explicitly defined to be Tue
/ __len__
doesn't give 0
.– jpp
Dec 31 '18 at 13:29
It's worth mentioning (since it wasn't obvious to me) that
NotImplemented
belongs to the class <class 'NotImplementedType'>
. Here, bool(NotImplemented)
evaluates to True
, because of some combination of: __bool__
undefined (most likely) / __bool__
explicitly defined to be Tue
/ __len__
doesn't give 0
.– jpp
Dec 31 '18 at 13:29
@jpp I don't think that class defines either
__bool__
or __len__
. I believe the spec dictates that the object is truthy unless __bool__
or __len__
say otherwise. You can read more here (that link is also included in the answer :-)).– coldspeed
Dec 31 '18 at 14:51
@jpp I don't think that class defines either
__bool__
or __len__
. I believe the spec dictates that the object is truthy unless __bool__
or __len__
say otherwise. You can read more here (that link is also included in the answer :-)).– coldspeed
Dec 31 '18 at 14:51
1
1
@coldspeed, Yup, I thought so. But it's worth clarification because new users may fall into the trap that
'a' == 'NotImplemented'
should return False
! While the underlying reason is you aren't working with strings but a NotImplementedType
object.– jpp
Dec 31 '18 at 14:54
@coldspeed, Yup, I thought so. But it's worth clarification because new users may fall into the trap that
'a' == 'NotImplemented'
should return False
! While the underlying reason is you aren't working with strings but a NotImplementedType
object.– jpp
Dec 31 '18 at 14:54
|
show 1 more comment
The result you are seeing is caused by
None.__eq__("a") # evaluates to NotImplemented
and NotImplemented
's truth value is documented to be True
:
https://docs.python.org/3/library/constants.html
Special value which should be returned by the binary special methods (e.g. eq(), lt(), add(), rsub(), etc.) to indicate that the operation is not implemented with respect to the other type; may be returned by the in-place binary special methods (e.g. imul(), iand(), etc.) for the same purpose. Its truth value is true.
If you call the __eq()__
method manually rather than just using ==
, you need to be prepared to deal with the possibility it may return NotImplemented
and that its truth value is true.
add a comment |
The result you are seeing is caused by
None.__eq__("a") # evaluates to NotImplemented
and NotImplemented
's truth value is documented to be True
:
https://docs.python.org/3/library/constants.html
Special value which should be returned by the binary special methods (e.g. eq(), lt(), add(), rsub(), etc.) to indicate that the operation is not implemented with respect to the other type; may be returned by the in-place binary special methods (e.g. imul(), iand(), etc.) for the same purpose. Its truth value is true.
If you call the __eq()__
method manually rather than just using ==
, you need to be prepared to deal with the possibility it may return NotImplemented
and that its truth value is true.
add a comment |
The result you are seeing is caused by
None.__eq__("a") # evaluates to NotImplemented
and NotImplemented
's truth value is documented to be True
:
https://docs.python.org/3/library/constants.html
Special value which should be returned by the binary special methods (e.g. eq(), lt(), add(), rsub(), etc.) to indicate that the operation is not implemented with respect to the other type; may be returned by the in-place binary special methods (e.g. imul(), iand(), etc.) for the same purpose. Its truth value is true.
If you call the __eq()__
method manually rather than just using ==
, you need to be prepared to deal with the possibility it may return NotImplemented
and that its truth value is true.
The result you are seeing is caused by
None.__eq__("a") # evaluates to NotImplemented
and NotImplemented
's truth value is documented to be True
:
https://docs.python.org/3/library/constants.html
Special value which should be returned by the binary special methods (e.g. eq(), lt(), add(), rsub(), etc.) to indicate that the operation is not implemented with respect to the other type; may be returned by the in-place binary special methods (e.g. imul(), iand(), etc.) for the same purpose. Its truth value is true.
If you call the __eq()__
method manually rather than just using ==
, you need to be prepared to deal with the possibility it may return NotImplemented
and that its truth value is true.
edited Jan 1 at 1:44
answered Dec 31 '18 at 6:19
Mark Meyer
36.3k32958
36.3k32958
add a comment |
add a comment |
As you already figured None.__eq__("a")
evaluates to NotImplemented
however if you try something like
if NotImplemented:
print("Yes")
else:
print("No")
the result is
yes
this mean that the truth value of NotImplemented
true
Therefor the outcome of the question is obvious:
None.__eq__(something)
yields NotImplemented
And bool(NotImplemented)
evaluates to True
So if None.__eq__("a")
is always True
New contributor
add a comment |
As you already figured None.__eq__("a")
evaluates to NotImplemented
however if you try something like
if NotImplemented:
print("Yes")
else:
print("No")
the result is
yes
this mean that the truth value of NotImplemented
true
Therefor the outcome of the question is obvious:
None.__eq__(something)
yields NotImplemented
And bool(NotImplemented)
evaluates to True
So if None.__eq__("a")
is always True
New contributor
add a comment |
As you already figured None.__eq__("a")
evaluates to NotImplemented
however if you try something like
if NotImplemented:
print("Yes")
else:
print("No")
the result is
yes
this mean that the truth value of NotImplemented
true
Therefor the outcome of the question is obvious:
None.__eq__(something)
yields NotImplemented
And bool(NotImplemented)
evaluates to True
So if None.__eq__("a")
is always True
New contributor
As you already figured None.__eq__("a")
evaluates to NotImplemented
however if you try something like
if NotImplemented:
print("Yes")
else:
print("No")
the result is
yes
this mean that the truth value of NotImplemented
true
Therefor the outcome of the question is obvious:
None.__eq__(something)
yields NotImplemented
And bool(NotImplemented)
evaluates to True
So if None.__eq__("a")
is always True
New contributor
edited Dec 31 '18 at 14:54
New contributor
answered Dec 31 '18 at 6:30
Kanjiu
2769
2769
New contributor
New contributor
add a comment |
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.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- 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%2f53984116%2fwhy-does-if-none-eq-a-evaluate-to-true%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
The title was wrong. The result is not
True
, as you noted yourself. It is a "truthy value", i.e. a valuex
such thatbool(x) is True
.– Bakuriu
yesterday
The title is fine. if [truthy value] evaluates to true.
– coldspeed
yesterday