Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

Python Object-Oriented Python Dice Roller Comparing and Combining Dice

Why don't you have to convert other to an int?

In Kenneth's video, he has defined magic methods that take argument 'other' such as:

def __add__(self, other):
    return int(self) + other

and

def __le__(self, other):
    return int(self) < other or int(self) == other

If you are comparing to dice instances, it would seem logical to me that you would have to convert the 'other' arg into an int as well, bc it will often just be an instance object of the Die class. But seems that he is able to add two dice objects together without converting 'other' to an int. I'm confused by this. Can anyone explain this to me? Thanks

3 Answers

Jeff Muday
MOD
Jeff Muday
Treehouse Moderator 28,717 Points

I recall when I first looked at Kenneth's lecture on this I had similar questions to yours. I am not a fan of overloading operators, but in some cases (like this) it makes a lot of sense.

The internal coersion like you mention would work fine, but there were a couple of "edge cases". The thing is that when using your own code you'd probably never run into the issue, but if you were preparing code to open-source into a python package, you have to try to anticipate some of the edge cases. Since your semantic interpretation might not be coincide with how others will interpret your code.

Here's my weak attempt to illustrate what is going on...

class MyDice:

... stuff omitted ...

    def __mul__(self, other):
        # the type coersion below might be problematic for a string.
        # also, you will only get ints back so even if other=3.14, it will be interpreted as 3
        return int(self) * int(other)

    def __div__(self, other):
        # the below line would allow a non-zero digit string to work (which might be fine)
        # a problem here is if other is between -1.0 and 1.0 we will get an unexpected DIVIDE BY ZERO error
        # another issue like the one in mul
        # is missing the resolution of the fractional portion of the float.
        return int(self)/int(other)
Jeff Muday
MOD
Jeff Muday
Treehouse Moderator 28,717 Points

Ryan,

This is a really good question-- and you could easily write your code with an extra conversion and it would work correctly for most design cases.

You do, however, run the risk of introducing some unintended "functionality" and might miss or create new error conditions where there should have been none.

Benefits of Internal Coersion

  • fewer type-coercions to perform, e.g. more flexible
  • could do math operations on string like numbers (this might be fine in many cases)
  • could do math operations on floats

Drawbacks and Potential for Error

  • you override some default string/integer operations (surprise!)

One such example is when you intend to multiply a string by an integer-- you are supposed to get the string repeated the number of times indicated by the integer. Instead, the code will throw an error -- for non-digit strings.

  • for that class, math operations with floats will always have integer results-- this is could be a major problem.

Often a Dice class in a simulation game is multiplied (or divided) by a random number normalized between 0 and 1. The result is always 0 when you multiply, or might encounter an unexpect DIVIDE BY ZERO fatal error during a division.

Best of luck with your Python journey. I can tell you will do well because of your curiosity!

Thanks Jeff - so are you saying that internal coercion is used to change 'other' to an int? Is this some magic? I still don't understand why 'other' doesn't need to be converted to int.

In treehouse slack channel, some advised that radd() reflects other so it gets converted to int. Without the radd() function defined, it would fail. But I tested and I see when I remove radd() the comparative operators (eg <=, >, ==) still work, so I'm thinking radd() doesn't have anything to do with it.

Thanks!