Why does `if None.__eq__(“a”)` evaluate to True?












74














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?










share|improve this question

















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 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
















74














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?










share|improve this question

















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 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














74












74








74


19





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?










share|improve this question















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






share|improve this question















share|improve this question













share|improve this question




share|improve this question








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 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 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 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












3 Answers
3






active

oldest

votes


















104














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




  1. First, (1).__eq__('a') is tried, which returns NotImplemented. This indicates that the operation is not supported, so


  2. 'a'.__eq__(1) is called, which also returns the same NotImplemented. So,

  3. 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 with is 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.






share|improve this answer



















  • 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








  • 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










  • 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








  • 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





















13














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.






share|improve this answer































    3














    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






    share|improve this answer










    New contributor




    Kanjiu is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
    Check out our Code of Conduct.


















      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%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









      104














      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




      1. First, (1).__eq__('a') is tried, which returns NotImplemented. This indicates that the operation is not supported, so


      2. 'a'.__eq__(1) is called, which also returns the same NotImplemented. So,

      3. 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 with is 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.






      share|improve this answer



















      • 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








      • 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










      • 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








      • 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


















      104














      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




      1. First, (1).__eq__('a') is tried, which returns NotImplemented. This indicates that the operation is not supported, so


      2. 'a'.__eq__(1) is called, which also returns the same NotImplemented. So,

      3. 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 with is 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.






      share|improve this answer



















      • 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








      • 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










      • 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








      • 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
















      104












      104








      104






      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




      1. First, (1).__eq__('a') is tried, which returns NotImplemented. This indicates that the operation is not supported, so


      2. 'a'.__eq__(1) is called, which also returns the same NotImplemented. So,

      3. 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 with is 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.






      share|improve this answer














      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




      1. First, (1).__eq__('a') is tried, which returns NotImplemented. This indicates that the operation is not supported, so


      2. 'a'.__eq__(1) is called, which also returns the same NotImplemented. So,

      3. 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 with is 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.







      share|improve this answer














      share|improve this answer



      share|improve this answer








      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 that None should be checked with is 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 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












      • @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 return False ! While the underlying reason is you aren't working with strings but a NotImplementedType object.
        – jpp
        Dec 31 '18 at 14:54
















      • 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








      • 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










      • 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








      • 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










      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















      13














      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.






      share|improve this answer




























        13














        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.






        share|improve this answer


























          13












          13








          13






          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.






          share|improve this answer














          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.







          share|improve this answer














          share|improve this answer



          share|improve this answer








          edited Jan 1 at 1:44

























          answered Dec 31 '18 at 6:19









          Mark Meyer

          36.3k32958




          36.3k32958























              3














              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






              share|improve this answer










              New contributor




              Kanjiu is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
              Check out our Code of Conduct.























                3














                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






                share|improve this answer










                New contributor




                Kanjiu is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
                Check out our Code of Conduct.





















                  3












                  3








                  3






                  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






                  share|improve this answer










                  New contributor




                  Kanjiu is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
                  Check out our Code of Conduct.









                  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







                  share|improve this answer










                  New contributor




                  Kanjiu is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
                  Check out our Code of Conduct.









                  share|improve this answer



                  share|improve this answer








                  edited Dec 31 '18 at 14:54





















                  New contributor




                  Kanjiu is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
                  Check out our Code of Conduct.









                  answered Dec 31 '18 at 6:30









                  Kanjiu

                  2769




                  2769




                  New contributor




                  Kanjiu is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
                  Check out our Code of Conduct.





                  New contributor





                  Kanjiu is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
                  Check out our Code of Conduct.






                  Kanjiu is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
                  Check out our Code of Conduct.






























                      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.





                      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.




                      draft saved


                      draft discarded














                      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





















































                      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

                      Сан-Квентин

                      Алькесар

                      Josef Freinademetz