Why does calling Python's 'magic method' not do type conversion like it would for the corresponding operator?












8















When I subtract a float from an integer (e.g. 1-2.0), Python does implicit type conversion (I think). But when I call what I thought was the same operation using the magic method __sub__, it suddenly does not anymore.



What am I missing here? When I overload operators for my own classes, is there a way around this other than explicitly casting input to whatever type I need?



a=1
a.__sub__(2.)
# returns NotImplemented
a.__rsub__(2.)
# returns NotImplemented
# yet, of course:
a-2.
# returns -1.0









share|improve this question



























    8















    When I subtract a float from an integer (e.g. 1-2.0), Python does implicit type conversion (I think). But when I call what I thought was the same operation using the magic method __sub__, it suddenly does not anymore.



    What am I missing here? When I overload operators for my own classes, is there a way around this other than explicitly casting input to whatever type I need?



    a=1
    a.__sub__(2.)
    # returns NotImplemented
    a.__rsub__(2.)
    # returns NotImplemented
    # yet, of course:
    a-2.
    # returns -1.0









    share|improve this question

























      8












      8








      8








      When I subtract a float from an integer (e.g. 1-2.0), Python does implicit type conversion (I think). But when I call what I thought was the same operation using the magic method __sub__, it suddenly does not anymore.



      What am I missing here? When I overload operators for my own classes, is there a way around this other than explicitly casting input to whatever type I need?



      a=1
      a.__sub__(2.)
      # returns NotImplemented
      a.__rsub__(2.)
      # returns NotImplemented
      # yet, of course:
      a-2.
      # returns -1.0









      share|improve this question














      When I subtract a float from an integer (e.g. 1-2.0), Python does implicit type conversion (I think). But when I call what I thought was the same operation using the magic method __sub__, it suddenly does not anymore.



      What am I missing here? When I overload operators for my own classes, is there a way around this other than explicitly casting input to whatever type I need?



      a=1
      a.__sub__(2.)
      # returns NotImplemented
      a.__rsub__(2.)
      # returns NotImplemented
      # yet, of course:
      a-2.
      # returns -1.0






      python casting






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked 4 hours ago









      dopplerdoppler

      1316




      1316
























          1 Answer
          1






          active

          oldest

          votes


















          14














          a - b isn't just a.__sub__(b). It also tries b.__rsub__(a) if a can't handle the operation, and in the 1 - 2. case, it's the float's __rsub__ that handles the operation.



          >>> (2.).__rsub__(1)
          -1.0


          You ran a.__rsub__(2.), but that's the wrong __rsub__. You need the right-side operand's __rsub__, not the left-side operand.





          There is no implicit type conversion built into the subtraction operator. float.__rsub__ has to handle ints manually. If you want type conversion in your own operator implementations, you'll have to handle that manually too.






          share|improve this answer





















          • 5





            It's worth noting that the NotImplemented result that is returned by the calls in the question are the signal to try the reverse method.

            – Blckknght
            4 hours ago











          • Thanks! I was aware it would try __rsub__ but didn't know it would reverse the argument order.

            – doppler
            3 hours ago






          • 1





            @doppler: It'd be pretty pointless to have the left operand handle both __sub__ and __rsub__. That'd just be two methods with the exact same job, and the right operand would have no opportunity to supply an implementation.

            – user2357112
            3 hours ago











          • @user2357112 so self.__rsub__(other) really just calls other.__sub__(self), if that makes any sense?

            – doppler
            3 hours ago






          • 2





            @doppler: No. self.__rsub__(other) is called for other - self if other can't handle it. Calling other.__sub__(self) would be pointless. We already know other can't handle it.

            – user2357112
            3 hours ago











          Your Answer






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

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

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

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


          }
          });














          draft saved

          draft discarded


















          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54775946%2fwhy-does-calling-pythons-magic-method-not-do-type-conversion-like-it-would-fo%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown

























          1 Answer
          1






          active

          oldest

          votes








          1 Answer
          1






          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes









          14














          a - b isn't just a.__sub__(b). It also tries b.__rsub__(a) if a can't handle the operation, and in the 1 - 2. case, it's the float's __rsub__ that handles the operation.



          >>> (2.).__rsub__(1)
          -1.0


          You ran a.__rsub__(2.), but that's the wrong __rsub__. You need the right-side operand's __rsub__, not the left-side operand.





          There is no implicit type conversion built into the subtraction operator. float.__rsub__ has to handle ints manually. If you want type conversion in your own operator implementations, you'll have to handle that manually too.






          share|improve this answer





















          • 5





            It's worth noting that the NotImplemented result that is returned by the calls in the question are the signal to try the reverse method.

            – Blckknght
            4 hours ago











          • Thanks! I was aware it would try __rsub__ but didn't know it would reverse the argument order.

            – doppler
            3 hours ago






          • 1





            @doppler: It'd be pretty pointless to have the left operand handle both __sub__ and __rsub__. That'd just be two methods with the exact same job, and the right operand would have no opportunity to supply an implementation.

            – user2357112
            3 hours ago











          • @user2357112 so self.__rsub__(other) really just calls other.__sub__(self), if that makes any sense?

            – doppler
            3 hours ago






          • 2





            @doppler: No. self.__rsub__(other) is called for other - self if other can't handle it. Calling other.__sub__(self) would be pointless. We already know other can't handle it.

            – user2357112
            3 hours ago
















          14














          a - b isn't just a.__sub__(b). It also tries b.__rsub__(a) if a can't handle the operation, and in the 1 - 2. case, it's the float's __rsub__ that handles the operation.



          >>> (2.).__rsub__(1)
          -1.0


          You ran a.__rsub__(2.), but that's the wrong __rsub__. You need the right-side operand's __rsub__, not the left-side operand.





          There is no implicit type conversion built into the subtraction operator. float.__rsub__ has to handle ints manually. If you want type conversion in your own operator implementations, you'll have to handle that manually too.






          share|improve this answer





















          • 5





            It's worth noting that the NotImplemented result that is returned by the calls in the question are the signal to try the reverse method.

            – Blckknght
            4 hours ago











          • Thanks! I was aware it would try __rsub__ but didn't know it would reverse the argument order.

            – doppler
            3 hours ago






          • 1





            @doppler: It'd be pretty pointless to have the left operand handle both __sub__ and __rsub__. That'd just be two methods with the exact same job, and the right operand would have no opportunity to supply an implementation.

            – user2357112
            3 hours ago











          • @user2357112 so self.__rsub__(other) really just calls other.__sub__(self), if that makes any sense?

            – doppler
            3 hours ago






          • 2





            @doppler: No. self.__rsub__(other) is called for other - self if other can't handle it. Calling other.__sub__(self) would be pointless. We already know other can't handle it.

            – user2357112
            3 hours ago














          14












          14








          14







          a - b isn't just a.__sub__(b). It also tries b.__rsub__(a) if a can't handle the operation, and in the 1 - 2. case, it's the float's __rsub__ that handles the operation.



          >>> (2.).__rsub__(1)
          -1.0


          You ran a.__rsub__(2.), but that's the wrong __rsub__. You need the right-side operand's __rsub__, not the left-side operand.





          There is no implicit type conversion built into the subtraction operator. float.__rsub__ has to handle ints manually. If you want type conversion in your own operator implementations, you'll have to handle that manually too.






          share|improve this answer















          a - b isn't just a.__sub__(b). It also tries b.__rsub__(a) if a can't handle the operation, and in the 1 - 2. case, it's the float's __rsub__ that handles the operation.



          >>> (2.).__rsub__(1)
          -1.0


          You ran a.__rsub__(2.), but that's the wrong __rsub__. You need the right-side operand's __rsub__, not the left-side operand.





          There is no implicit type conversion built into the subtraction operator. float.__rsub__ has to handle ints manually. If you want type conversion in your own operator implementations, you'll have to handle that manually too.







          share|improve this answer














          share|improve this answer



          share|improve this answer








          edited 4 hours ago

























          answered 4 hours ago









          user2357112user2357112

          155k12163258




          155k12163258








          • 5





            It's worth noting that the NotImplemented result that is returned by the calls in the question are the signal to try the reverse method.

            – Blckknght
            4 hours ago











          • Thanks! I was aware it would try __rsub__ but didn't know it would reverse the argument order.

            – doppler
            3 hours ago






          • 1





            @doppler: It'd be pretty pointless to have the left operand handle both __sub__ and __rsub__. That'd just be two methods with the exact same job, and the right operand would have no opportunity to supply an implementation.

            – user2357112
            3 hours ago











          • @user2357112 so self.__rsub__(other) really just calls other.__sub__(self), if that makes any sense?

            – doppler
            3 hours ago






          • 2





            @doppler: No. self.__rsub__(other) is called for other - self if other can't handle it. Calling other.__sub__(self) would be pointless. We already know other can't handle it.

            – user2357112
            3 hours ago














          • 5





            It's worth noting that the NotImplemented result that is returned by the calls in the question are the signal to try the reverse method.

            – Blckknght
            4 hours ago











          • Thanks! I was aware it would try __rsub__ but didn't know it would reverse the argument order.

            – doppler
            3 hours ago






          • 1





            @doppler: It'd be pretty pointless to have the left operand handle both __sub__ and __rsub__. That'd just be two methods with the exact same job, and the right operand would have no opportunity to supply an implementation.

            – user2357112
            3 hours ago











          • @user2357112 so self.__rsub__(other) really just calls other.__sub__(self), if that makes any sense?

            – doppler
            3 hours ago






          • 2





            @doppler: No. self.__rsub__(other) is called for other - self if other can't handle it. Calling other.__sub__(self) would be pointless. We already know other can't handle it.

            – user2357112
            3 hours ago








          5




          5





          It's worth noting that the NotImplemented result that is returned by the calls in the question are the signal to try the reverse method.

          – Blckknght
          4 hours ago





          It's worth noting that the NotImplemented result that is returned by the calls in the question are the signal to try the reverse method.

          – Blckknght
          4 hours ago













          Thanks! I was aware it would try __rsub__ but didn't know it would reverse the argument order.

          – doppler
          3 hours ago





          Thanks! I was aware it would try __rsub__ but didn't know it would reverse the argument order.

          – doppler
          3 hours ago




          1




          1





          @doppler: It'd be pretty pointless to have the left operand handle both __sub__ and __rsub__. That'd just be two methods with the exact same job, and the right operand would have no opportunity to supply an implementation.

          – user2357112
          3 hours ago





          @doppler: It'd be pretty pointless to have the left operand handle both __sub__ and __rsub__. That'd just be two methods with the exact same job, and the right operand would have no opportunity to supply an implementation.

          – user2357112
          3 hours ago













          @user2357112 so self.__rsub__(other) really just calls other.__sub__(self), if that makes any sense?

          – doppler
          3 hours ago





          @user2357112 so self.__rsub__(other) really just calls other.__sub__(self), if that makes any sense?

          – doppler
          3 hours ago




          2




          2





          @doppler: No. self.__rsub__(other) is called for other - self if other can't handle it. Calling other.__sub__(self) would be pointless. We already know other can't handle it.

          – user2357112
          3 hours ago





          @doppler: No. self.__rsub__(other) is called for other - self if other can't handle it. Calling other.__sub__(self) would be pointless. We already know other can't handle it.

          – user2357112
          3 hours ago




















          draft saved

          draft discarded




















































          Thanks for contributing an answer to Stack Overflow!


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

          But avoid



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

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


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




          draft saved


          draft discarded














          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54775946%2fwhy-does-calling-pythons-magic-method-not-do-type-conversion-like-it-would-fo%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

          How to reconfigure Docker Trusted Registry 2.x.x to use CEPH FS mount instead of NFS and other traditional...

          is 'sed' thread safe

          How to make a Squid Proxy server?