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





.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty{ height:90px;width:728px;box-sizing:border-box;
}







141















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































    141















    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



























      141












      141








      141


      24






      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 14 hours ago









      Mark Amery

      65.5k31259305




      65.5k31259305










      asked Dec 31 '18 at 6:03









      The AI ArchitectThe AI Architect

      9192918




      9192918
























          4 Answers
          4






          active

          oldest

          votes


















          172














          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





















          • 6





            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








          • 4





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

            – cs95
            Dec 31 '18 at 12:12






          • 2





            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








          • 2





            @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 :-)).

            – cs95
            Dec 31 '18 at 14:51








          • 2





            @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





















          33














          The result you are seeing is caused by that fact that



          None.__eq__("a") # evaluates to NotImplemented


          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

































            16














            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

































              1














              Why?



              It returns a NotImplemented, yeah:



              >>> None.__eq__('a')
              NotImplemented
              >>>


              But if you look at this:



              >>> bool(NotImplemented)
              True
              >>>


              NotImplemented is actually a truthy value, so that's why it returns b, anything that is True will pass, anything that is False wouldn't.



              How to solve it?



              You have to check if it is True, so be more suspicious, as you see:



              >>> NotImplemented == True
              False
              >>>


              So you would do:



              >>> if None.__eq__('a') == True:
              print('b')


              >>>


              And as you see, it wouldn't return anything.






              share|improve this answer



















              • 1





                most visually clear answer - v worthwhile addition - thank you

                – scharfmn
                Jan 29 at 19:27











              • @scharfmn Lol, happy that i posted a good answer :-)

                – U9-Forward
                Jan 30 at 0:14






              • 1





                :) “worthwhile addition” doesn’t quite capture what I was trying to say (as you obv see) - maybe “belated excellence” is what I wanted - cheers

                – scharfmn
                Jan 30 at 0:25






              • 1





                @scharfmn Yeah, i was bored, so answer, lol :-) ...

                – U9-Forward
                Jan 30 at 0:26











              • @scharfmn yes? I'm curious to know what you think this answer adds that hasn't already been covered before.

                – cs95
                Feb 1 at 22:43










              protected by kmario23 Mar 6 at 4:44



              Thank you for your interest in this question.
              Because it has attracted low-quality or spam answers that had to be removed, posting an answer now requires 10 reputation on this site (the association bonus does not count).



              Would you like to answer one of these unanswered questions instead?














              4 Answers
              4






              active

              oldest

              votes








              4 Answers
              4






              active

              oldest

              votes









              active

              oldest

              votes






              active

              oldest

              votes









              172














              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





















              • 6





                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








              • 4





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

                – cs95
                Dec 31 '18 at 12:12






              • 2





                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








              • 2





                @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 :-)).

                – cs95
                Dec 31 '18 at 14:51








              • 2





                @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


















              172














              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





















              • 6





                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








              • 4





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

                – cs95
                Dec 31 '18 at 12:12






              • 2





                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








              • 2





                @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 :-)).

                – cs95
                Dec 31 '18 at 14:51








              • 2





                @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
















              172












              172








              172







              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









              cs95cs95

              143k25165251




              143k25165251








              • 6





                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








              • 4





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

                – cs95
                Dec 31 '18 at 12:12






              • 2





                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








              • 2





                @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 :-)).

                – cs95
                Dec 31 '18 at 14:51








              • 2





                @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
















              • 6





                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








              • 4





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

                – cs95
                Dec 31 '18 at 12:12






              • 2





                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








              • 2





                @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 :-)).

                – cs95
                Dec 31 '18 at 14:51








              • 2





                @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










              6




              6





              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






              4




              4





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

              – cs95
              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!

              – cs95
              Dec 31 '18 at 12:12




              2




              2





              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






              2




              2





              @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 :-)).

              – cs95
              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 :-)).

              – cs95
              Dec 31 '18 at 14:51






              2




              2





              @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















              33














              The result you are seeing is caused by that fact that



              None.__eq__("a") # evaluates to NotImplemented


              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






























                33














                The result you are seeing is caused by that fact that



                None.__eq__("a") # evaluates to NotImplemented


                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




























                  33












                  33








                  33







                  The result you are seeing is caused by that fact that



                  None.__eq__("a") # evaluates to NotImplemented


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



                  None.__eq__("a") # evaluates to NotImplemented


                  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 12 at 1:59

























                  answered Dec 31 '18 at 6:19









                  Mark MeyerMark Meyer

                  41.9k33665




                  41.9k33665























                      16














                      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






























                        16














                        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




























                          16












                          16








                          16







                          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















                          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














                          share|improve this answer



                          share|improve this answer








                          edited Dec 31 '18 at 14:54

























                          answered Dec 31 '18 at 6:30









                          KanjiuKanjiu

                          42110




                          42110























                              1














                              Why?



                              It returns a NotImplemented, yeah:



                              >>> None.__eq__('a')
                              NotImplemented
                              >>>


                              But if you look at this:



                              >>> bool(NotImplemented)
                              True
                              >>>


                              NotImplemented is actually a truthy value, so that's why it returns b, anything that is True will pass, anything that is False wouldn't.



                              How to solve it?



                              You have to check if it is True, so be more suspicious, as you see:



                              >>> NotImplemented == True
                              False
                              >>>


                              So you would do:



                              >>> if None.__eq__('a') == True:
                              print('b')


                              >>>


                              And as you see, it wouldn't return anything.






                              share|improve this answer



















                              • 1





                                most visually clear answer - v worthwhile addition - thank you

                                – scharfmn
                                Jan 29 at 19:27











                              • @scharfmn Lol, happy that i posted a good answer :-)

                                – U9-Forward
                                Jan 30 at 0:14






                              • 1





                                :) “worthwhile addition” doesn’t quite capture what I was trying to say (as you obv see) - maybe “belated excellence” is what I wanted - cheers

                                – scharfmn
                                Jan 30 at 0:25






                              • 1





                                @scharfmn Yeah, i was bored, so answer, lol :-) ...

                                – U9-Forward
                                Jan 30 at 0:26











                              • @scharfmn yes? I'm curious to know what you think this answer adds that hasn't already been covered before.

                                – cs95
                                Feb 1 at 22:43
















                              1














                              Why?



                              It returns a NotImplemented, yeah:



                              >>> None.__eq__('a')
                              NotImplemented
                              >>>


                              But if you look at this:



                              >>> bool(NotImplemented)
                              True
                              >>>


                              NotImplemented is actually a truthy value, so that's why it returns b, anything that is True will pass, anything that is False wouldn't.



                              How to solve it?



                              You have to check if it is True, so be more suspicious, as you see:



                              >>> NotImplemented == True
                              False
                              >>>


                              So you would do:



                              >>> if None.__eq__('a') == True:
                              print('b')


                              >>>


                              And as you see, it wouldn't return anything.






                              share|improve this answer



















                              • 1





                                most visually clear answer - v worthwhile addition - thank you

                                – scharfmn
                                Jan 29 at 19:27











                              • @scharfmn Lol, happy that i posted a good answer :-)

                                – U9-Forward
                                Jan 30 at 0:14






                              • 1





                                :) “worthwhile addition” doesn’t quite capture what I was trying to say (as you obv see) - maybe “belated excellence” is what I wanted - cheers

                                – scharfmn
                                Jan 30 at 0:25






                              • 1





                                @scharfmn Yeah, i was bored, so answer, lol :-) ...

                                – U9-Forward
                                Jan 30 at 0:26











                              • @scharfmn yes? I'm curious to know what you think this answer adds that hasn't already been covered before.

                                – cs95
                                Feb 1 at 22:43














                              1












                              1








                              1







                              Why?



                              It returns a NotImplemented, yeah:



                              >>> None.__eq__('a')
                              NotImplemented
                              >>>


                              But if you look at this:



                              >>> bool(NotImplemented)
                              True
                              >>>


                              NotImplemented is actually a truthy value, so that's why it returns b, anything that is True will pass, anything that is False wouldn't.



                              How to solve it?



                              You have to check if it is True, so be more suspicious, as you see:



                              >>> NotImplemented == True
                              False
                              >>>


                              So you would do:



                              >>> if None.__eq__('a') == True:
                              print('b')


                              >>>


                              And as you see, it wouldn't return anything.






                              share|improve this answer













                              Why?



                              It returns a NotImplemented, yeah:



                              >>> None.__eq__('a')
                              NotImplemented
                              >>>


                              But if you look at this:



                              >>> bool(NotImplemented)
                              True
                              >>>


                              NotImplemented is actually a truthy value, so that's why it returns b, anything that is True will pass, anything that is False wouldn't.



                              How to solve it?



                              You have to check if it is True, so be more suspicious, as you see:



                              >>> NotImplemented == True
                              False
                              >>>


                              So you would do:



                              >>> if None.__eq__('a') == True:
                              print('b')


                              >>>


                              And as you see, it wouldn't return anything.







                              share|improve this answer












                              share|improve this answer



                              share|improve this answer










                              answered Jan 28 at 6:15









                              U9-ForwardU9-Forward

                              18.6k51744




                              18.6k51744








                              • 1





                                most visually clear answer - v worthwhile addition - thank you

                                – scharfmn
                                Jan 29 at 19:27











                              • @scharfmn Lol, happy that i posted a good answer :-)

                                – U9-Forward
                                Jan 30 at 0:14






                              • 1





                                :) “worthwhile addition” doesn’t quite capture what I was trying to say (as you obv see) - maybe “belated excellence” is what I wanted - cheers

                                – scharfmn
                                Jan 30 at 0:25






                              • 1





                                @scharfmn Yeah, i was bored, so answer, lol :-) ...

                                – U9-Forward
                                Jan 30 at 0:26











                              • @scharfmn yes? I'm curious to know what you think this answer adds that hasn't already been covered before.

                                – cs95
                                Feb 1 at 22:43














                              • 1





                                most visually clear answer - v worthwhile addition - thank you

                                – scharfmn
                                Jan 29 at 19:27











                              • @scharfmn Lol, happy that i posted a good answer :-)

                                – U9-Forward
                                Jan 30 at 0:14






                              • 1





                                :) “worthwhile addition” doesn’t quite capture what I was trying to say (as you obv see) - maybe “belated excellence” is what I wanted - cheers

                                – scharfmn
                                Jan 30 at 0:25






                              • 1





                                @scharfmn Yeah, i was bored, so answer, lol :-) ...

                                – U9-Forward
                                Jan 30 at 0:26











                              • @scharfmn yes? I'm curious to know what you think this answer adds that hasn't already been covered before.

                                – cs95
                                Feb 1 at 22:43








                              1




                              1





                              most visually clear answer - v worthwhile addition - thank you

                              – scharfmn
                              Jan 29 at 19:27





                              most visually clear answer - v worthwhile addition - thank you

                              – scharfmn
                              Jan 29 at 19:27













                              @scharfmn Lol, happy that i posted a good answer :-)

                              – U9-Forward
                              Jan 30 at 0:14





                              @scharfmn Lol, happy that i posted a good answer :-)

                              – U9-Forward
                              Jan 30 at 0:14




                              1




                              1





                              :) “worthwhile addition” doesn’t quite capture what I was trying to say (as you obv see) - maybe “belated excellence” is what I wanted - cheers

                              – scharfmn
                              Jan 30 at 0:25





                              :) “worthwhile addition” doesn’t quite capture what I was trying to say (as you obv see) - maybe “belated excellence” is what I wanted - cheers

                              – scharfmn
                              Jan 30 at 0:25




                              1




                              1





                              @scharfmn Yeah, i was bored, so answer, lol :-) ...

                              – U9-Forward
                              Jan 30 at 0:26





                              @scharfmn Yeah, i was bored, so answer, lol :-) ...

                              – U9-Forward
                              Jan 30 at 0:26













                              @scharfmn yes? I'm curious to know what you think this answer adds that hasn't already been covered before.

                              – cs95
                              Feb 1 at 22:43





                              @scharfmn yes? I'm curious to know what you think this answer adds that hasn't already been covered before.

                              – cs95
                              Feb 1 at 22:43





                              protected by kmario23 Mar 6 at 4:44



                              Thank you for your interest in this question.
                              Because it has attracted low-quality or spam answers that had to be removed, posting an answer now requires 10 reputation on this site (the association bonus does not count).



                              Would you like to answer one of these unanswered questions instead?



                              Popular posts from this blog

                              Biblatex bibliography style without URLs when DOI exists (in Overleaf with Zotero bibliography)

                              ComboBox Display Member on multiple fields

                              Is it possible to collect Nectar points via Trainline?