# class representing a fraction
class fraction:
def __init__(self,n,d): # initialize numerator and denominator
self.n = n
if d==0: raise "zero denominator error"
self.d = d
# constructor
# method to return string representation of class:
def tostring(self):
return str(self.n)+"/"+str(self.d)
# tostring
# method to simplify fraction by calculating the gcd
def simplify(self):
a = self.n # rename vars for convenience
b = self.d
while (a!=0 and b!=0): #find gcd of a and b
if (a>b): a = a%b
else: b = b%a
# while
gcd = a+b # gcd is the number that's not zero
self.n = self.n / gcd # simplify numerator and denominator
self.d = self.d /gcd
#simplify
def multiply(self,B): # multiply this fraction with another fraction B
n = self.n * B.n
d = self.d * B.d
newobject = fraction(n,d)
return newobject
# multiply
# is multiply a destructive or non-destructive function?
# ----------- operator overloading ----------------
def __mul__(self,B): # overrides the * operator
return self.multiply(B)
# __mul__
def dmult(self,B): # destructive version of multiply: changes self
self.n = self.n * B.n
self.d = self.d * B.d
# destructive multiplication
def __add__(A,B):
n = A.n*B.d + B.n*A.d
d = A.d * B.d
return fraction(n,d)
# add
def __eq__(A,B):
return A.n*B.d == A.d*B.n
# equals
# class fraction
#####
f1 = fraction(1,2)
f2 = fraction(2,4)
f3 = fraction(2,8)
print f1 # don't expect to see 1/2
print f1.tostring()
print f1 == f2
f4 = f1 + f3 # f1.add(f3)
print f4.tostring()
f4.simplify()
print f4.tostring()
#############
### Summary:
# In order to create a class of objects, I must first be clear as to:
# 1. The attributes or "fields" of the object. That is, what are the
# pieces of data that will make up the object. In the case of fractions,
# these are the numerator and the denominator.
# 2. What functions (methods) do I wish to be able to call on each object.
#
# Once I'm clear as to what needs to be done. I can now write a class
# structure in Python. The first method I should write (usually) is the
# "constructor" function, which must be called __init__. It is the job
# of this function to assign initial values to the variables (fields)
# representing each object.
print "-------------- Class Excercise - Pun Intended -------------"
# I want to have objects representing collections of coins (i.e., piggybanks).
# The coin denominations are nickels, dimes, and quarters (we're snobs and
# don't collect pennies). When the a coin-collection
# object is first created, it will contain 0 nickels, 0 dimes and 0 quarters.
# The methods that I want to call
# are
# addquarter(), adddime(), addnickel(), totalworth(),
#
# That is, the following code needs to be valid with your class:
# mybank = piggybank()
# mybank.adddime()
# mybank.addquarter()
# mybank.addnickel()
# print mybank.totalworth() # should print 40 cents
## Now you're going to add another method to the class. You want to
# *merge* the contents of two piggybanks into one:
# yourbank = piggybank()
# yourbank.addnickel()
# yourbank.addquarter()
# yourbank.merge(mybank) # add mybank's contents to yourbank
# print yourbank.totalworth() # should print 70 cents
# print mybank.totalworth() # should print 0 cents: you stole my money.
######################### ONE MORE IMPORTANT THING ###########################
#You were first introduced to the concept of pointers with respect to arrays.
#Arrays are special kinds of objects. Objects in Python are also referenced
#through pointers. This means that if I do:
# mybank = yourbank
# it does not duplicate the yourbank object, rather it would just set mybank
# to the memory address of where yourbank is stored. It doesn't copy the
# object. So remember, when you assign a variable to an object, the variable
# is actually only assigned to the memory address of the object.
class demo:
def __init__(this,a):
this.x = a
#init
#demo
def f(x,D):
x = 2
D.x = 2
#f
x = 1
D = demo(1)
f(x,D)
print x, D.x # prints 1, then 2
# x stays 1 because the x inside the function f is a local x. The D inside
# the function f is also local to f (because it's a parameter), but it
# points to the same object that the D outside points to. So when D.x is
# changed to 2, it affects the same object that the other D points to as well.
# Had I tried to do the following inside f: D = demo(2). Then the D inside
# f will be set to a different object, but the D outside will still point to
# the original object, which hasn't been changed. In this case it will still
# print 1 for D.x