A document from MCS 275 Spring 2021, instructor David Dumas. You can also get the notebook file.

Quiz 3 Solutions

MCS 275 Spring 2021 - David Dumas

Problem 2: Arithmetic forbidden - 4 points

THIS IS THE ONLY PROBLEM ON THE QUIZ

Make a subclass of the built-in class int called NoArithInt which "forbids arithmetic", meaning that it is not possible to use the operations +, -, *, or / with two instances of NoArithInt.

Save your class definition in a file called quiz3prob2.py and submit it.

Your subclass should NOT have its own constructor, because int already has one that does everything needed. The only methods in your subclass should be special methods that handle the arithmetic operations listed above.

In [2]:
# MCS 275 Quiz 3 Problem 2: Minimal Solution
# Jennifer Vaccaro
# This code is my own work, written in 
# accordance with the rules in the syllabus.

class NoArithInt(int):
    """Subclass of int that does not allow operators +,-,*,/"""
    def __add__(self, other):
        """Return NotImplemented, since you cannot add NoArithInts."""
        # Always returns NotImplemented, independent of the type of other
        return NotImplemented

    def __sub__(self,other):
        """Return NotImplemented, since you cannot subtract NoArithInts."""
        return NotImplemented

    def __mul__(self, other):
        """Return NotImplemented, since you cannot multiply NoArithInts."""
        return NotImplemented

    def __truediv__(self, other):
        """Return NotImplemented, since you cannot divide NoArithInts."""
        return NotImplemented

    #You do not need to implement radd, rmul, etc. since those will only be used when the "left side" of the operator is NOT a NoArithInt.

Here are some test cases with integers.

In [3]:
# make some instances of int
x = 5
y = 15
# Test that arithmetic between ints works
print(x+y) # 20
print(x-y) # -10
print(x*y) # 75
print(y/x) # 3.0
20
-10
75
3.0

And here are some similar statements that attempt to do arithmetic with NoArithInt objects, which should fail. It is assumed here that NoArithInt is available in the same scope as this code is run, so you might need to change it to quiz3prob2.NoArithInt and add import quiz3prob2 if you're running these statements in a separate file.

In [4]:
# make some no arithmetic integers
x = NoArithInt(5)
y = NoArithInt(15)

# Test that arithmetic between NoArithInt instances fails.

# should give TypeError: unsupported operand type(s) for +: 'NoArithInt' and 'NoArithInt'
print(x+y)

# should give TypeError: unsupported operand type(s) for -: 'NoArithInt' and 'NoArithInt'
print(x-y)

# should give TypeError: unsupported operand type(s) for *: 'NoArithInt' and 'NoArithInt'
print(x*y)

# should give TypeError: unsupported operand type(s) for /: 'NoArithInt' and 'NoArithInt'
print(y/x)

# WARNING: To test the print() statements above, you'll need to run them one at a time.
# If you just copy all of them into a file and run it, execution will stop as soon as
# the first one raises an exception.
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-4-ab717b871d7d> in <module>
      6 
      7 # should give TypeError: unsupported operand type(s) for +: 'NoArithInt' and 'NoArithInt'
----> 8 print(x+y)
      9 
     10 # should give TypeError: unsupported operand type(s) for -: 'NoArithInt' and 'NoArithInt'

TypeError: unsupported operand type(s) for +: 'NoArithInt' and 'NoArithInt'

Here's a bonus solution, which considers a different behavior for the case when "other" is NOT a NoArithInt. Specifically, it uses super() to recreate the behavior of performing arithmentic between an int and other.

In [ ]:
# MCS 275 Quiz 3 Problem 2: Supplementary Solution
# Jennifer Vaccaro
# This code is my own work, written in 
# accordance with the rules in the syllabus.

class NoArithInt(int):
    """Subclass of int that does not allow operators +,-,*,/"""
    def __add__(self, other):
        """Return NotImplemented if other is a NoArithInt
        otherwise, behave like an integer and add."""
        # Check the type of other...if it's a NoArithInt, then
        # returning NotImplemented will raise the appropriate TypeError
        if isinstance(other, NoArithInt):
            return NotImplemented
        else:
            # otherwise, add the "other" item to self as if 
            # self is an integer, using super()
            return super().__add__(other)
            
    def __sub__(self,other):
        """Return NotImplemented if other is a NoArithInt
        otherwise, behave like an integer and subtract."""
        if isinstance(other, NoArithInt):
            return NotImplemented
        else:
            return super().__sub__(other)

    def __mul__(self, other):
        """Return NotImplemented if other is a NoArithInt
        otherwise, behave like an integer and multiply."""
        if isinstance(other, NoArithInt):
            return NotImplemented
        else:
            return super().__mul__(other)

    def __truediv__(self, other):
        """Return NotImplemented if other is a NoArithInt
        otherwise, behave like an integer and divide."""
        if isinstance(other, NoArithInt):
            return NotImplemented
        else:
            return super().__truediv__(other)
    
    #Again, you do not need to implement radd, rmul, etc., but this solution means that operators will behave commutatively.

Finally, here are some test cases that check the behavior if arithmetic is used between a NoArithInt and another type.

In [5]:
a = 5
b = 3.5
c = "hello!"
x = NoArithInt(15)
print(a+x) # int + NoArithInt, should be 20
print(x+a) # NoArithInt + int, should be 20
print(b+x) # float + NoArithInt, should be 18.5
print(x+b) # NoArithInt + float, should be 18.5
print(x+c) # NoArithInt + string, should fail (like an int would!)
20
20
18.5
18.5
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-5-372de2a3130e> in <module>
      7 print(b+x) # float + NoArithInt, should be 18.5
      8 print(x+b) # NoArithInt + float, should be 18.5
----> 9 print(x+c) # NoArithInt + string, should fail.

TypeError: unsupported operand type(s) for +: 'NoArithInt' and 'str'