As class Rational is currently implemented, the client may modify the attributes (i.e., sign, numerator and denominator) and place the data in an inconsistent state. Modify the def- inition for class Rational from Exercise 8.5 to include method __setitem__. If a client at- tempts to change the numerator or denominator of an object of class Rational, __setitem__ determines whether the change

affects the sign of the object. If so, the method changes the object’s sign and sets the numerator or denominator as the absolute value of the client-specified value. The method also should call method simplify to reduce the object. Beware: If __setitem__ assigns a value to an attribute through the dot access operator, Python invokes __setitem__ again, result- ing in infinite recursion. Make sure the method makes assignments through the object’s __dict__ attribute instead. [Note: Methods __init__ and simplify also must be updated to use the ob- ject’s __dict__, to avoid infinite recursion].

What will be an ideal response?


```
# Definition of class Rational with __setattr__.

def gcd( x, y ):
"""Computes greatest common divisor of two values"""

while y:
z = x
x = y
y = z % y

return x

class Rational:
"""Representation of rational number"""

def __init__( self, top = 1, bottom = 1 ):
"""Initializes Rational instance"""

# do not allow 0 denominator
if bottom == 0:
raise ZeroDivisionError, "Cannot have 0 denominator"

# assign attribute values
self.__dict__[ "numerator" ] = abs( top )
self.__dict__[ "denominator" ] = abs( bottom )
self.__dict__[ "sign" ] = ( top * bottom ) / \
( self.numerator * self.denominator )

self.simplify() # Rational represented in reduced form

def simplify( self ):
"""Simplifies a Rational number"""

common = gcd( self.numerator, self.denominator )
self.__dict__[ "numerator" ] /= common
self.__dict__[ "denominator" ] /= common

# overloaded attribute access
def __setattr__( self, name, value ):
"""Overloaded attribute assignment"""

# update sign if necessary for changes numerator/denominator
if name == "numerator" or name == "denominator":

if value / abs( value ) != self.sign or
( value / abs( value ) == -1 == self.sign ):
self.__dict__[ "sign" ] *= -1

self.__dict__[ name ] = abs( value )
self.simplify()
else:
self.__dict__[ name ] = value # default assignment

# overloaded unary operator
def __neg__( self ):
"""Overloaded negation operator"""

return Rational( -self.sign * self.numerator,
self.denominator )

# overloaded binary arithmetic operators
def __add__( self, other ):
"""Overloaded addition operator"""

return Rational(
self.sign * self.numerator * other.denominator +
other.sign * other.numerator * self.denominator,
self.denominator * other.denominator )

def __radd__( self, other ):
"""Overloaded right addition operator"""

return self.__add__( other )

def __sub__( self, other ):
"""Overloaded subtraction operator"""

return self + ( -other )

def __rsub__( self, other ):
"""Overloaded right subtraction operator"""

return other + ( -self )

def __mul__( self, other ):
"""Overloaded multiplication operator"""

return Rational( self.numerator * other.numerator,
self.sign * self.denominator *
other.sign * other.denominator )

def __rmul__( self, other ):
"""Overloaded right multiplication operator"""

return self.__mul__( other )

def __div__( self, other ):
"""Overloaded / division operator."""

return Rational( self.numerator * other.denominator,
self.sign * self.denominator *
other.sign * other.numerator )

def __rdiv__( self, other ):
"""Overloaded right / division operator."""

return Rational( other.numerator * self.denominator,
other.sign * other.denominator *
self.sign * self.numerator )

def __truediv__( self, other ):
"""Overloaded / division operator. (For use with
Python versions that contain the // operator)"""

return self.__div__( other )

def __rtruediv__( self, other ):
"""Overloaded right / division operator. (For use with
Python versions that contain the // operator)"""

return self.__rdiv__( other )

# overloaded binary comparison operators
def __eq__( self, other ):
"""Overloaded equality operator"""

return ( self - other ).numerator == 0

def __lt__( self, other ):
"""Overloaded less than operator"""

return ( self - other ).sign < 0

def __gt__( self, other ):
"""Overloaded greater than operator"""

return ( self - other ).sign > 0

# overloaded built-in functions
def __abs__( self ):
"""Overloaded built-in function abs"""

return Rational( self.numerator, self.denominator )

def __str__( self ):
"""String representation"""

# determine sign display
if self.sign == -1:
signString = "-"
else:
signString = ""

if self.numerator == 0:
return "0"
elif self.denominator == 1:
return "%s%d" % ( signString, self.numerator )
else:
return "%s%d/%d" % \
( signString, self.numerator, self.denominator )

# overloaded coercion capability
def __int__( self ):
"""Overloaded integer representation"""

return self.sign * divmod( self.numerator,
self.denominator )[ 0 ]

def __float__( self ):
"""Overloaded integer representation"""

return self.sign * float( self.numerator ) / self.denominator

def __coerce__( self, other ):
"""Overloaded coercion. Can only coerce int to Rational"""

if type( other ) == type( 1 ):
return ( self, Rational( other ) )
else:
return None
```
>>> r = Rational( 3, 4 )
>>> print r
3/4
>>> r.numerator = -3
>>> print r
-3/4
>>> r.denominator = -5
>>> print r
3/5

Computer Science & Information Technology

You might also like to view...

What is the value returned by the following function?

int function() { int value = 35; return value + 5; value += 10; } a. 35 b. 40 c. 50 d. 10

Computer Science & Information Technology

Assigning a subclass reference to a superclass variable is safe ________.

a. because the subclass object has an object of its superclass. b. because the subclass object is an object of its superclass. c. only when the superclass is abstract. d. only when the superclass is concrete.

Computer Science & Information Technology

Which control is used to add a report to another report?

A. text box B. combo box C. subreport D. group section

Computer Science & Information Technology

The ________________ property specifies the maximum number of characters the text box will accept.

A. MaxChar B. MaxStr C. MaxTxt D. MaxLength

Computer Science & Information Technology