Comparing Objects for Equality
• Earlier in course, we saw ==
compare object contents
§ This is not the default
§ Default: folder names
• Must implement __eq__
§ Operator overloading!
§ Not limited to simple
attribute comparison
§ Ex: cross multiplying
1 2
2 4
class Fraction(object):
"""Instance attributes:
_numerator: top [int]
_denominator: bottom [int > 0]"""
def __eq__(self,q):
"""Returns: True if self, q equal,
False if not, or q not a Fraction"""
if type(q) != Fraction:
return False
left = self._numerator*q._denominator
rght = self._denominator*q._numerator
return left == rght
4 4
is Versus ==
• p is q evaluates to False
§ Compares folder names
§ Cannot change this
• p == q evaluates to True
§ But only because method
__eq__ compares contents
id2
Point
id2
p
id3
q
x 2.2
y
z
5.4
6.7
id3
Point
x 2.2
y
z
5.4
6.7
Always use (x is None) not (x == None)
Recall: Overloading Multiplication
class Fraction(object):
"""Instance attributes:
_numerator [int]: top
_denominator [int > 0]: bottom """
def __mul__(self,q):
"""Returns: Product of self, q
Makes a new Fraction; does not
modify contents of self or q
Precondition: q a Fraction"""
assert type(q) == Fraction
top = self._numerator*q._numerator
bot= self._denominator*q._denominator
return Fraction(top,bot)
>>> p = Fraction(1,2)
>>> q = 2 # an int
>>> r = p*q
>>> r = p.__mul__(q) # ERROR
Python
converts to
Can only multiply fractions.
But ints “make sense” too.
Solution: Look at Argument Type
• Overloading use left type
§ p*q => p.__mul__(q)
§ Done for us automatically
§ Looks in class definition
• What about type on right?
§ Have to handle ourselves
• Can implement with ifs
§ Write helper for each type
§ Check type in method
§ Send to appropriate helper
class Fraction(object):
…
def __mul__(self,q):
"""Returns: Product of self, q
Precondition: q a Fraction or int"""
if type(q) == Fraction:
return self._mulFrac(q)
elif type(q) == int:
return self._mulInt(q)
…
def _mulInt(self,q): # Hidden method
return Fraction(self._numerator*q,
self._denominator)
A Better Multiplication
class Fraction(object):
…
def __mul__(self,q):
"""Returns: Product of self, q
Precondition: q a Fraction or int"""
if type(q) == Fraction:
return self._mulFrac(q)
elif type(q) == int:
return self._mulInt(q)
…
def _mulInt(self,q): # Hidden method
return Fraction(self._numerator*q,
self._denominator)
>>> p = Fraction(1,2)
>>> q = 2 # an int
>>> r = p*q
>>> r = p.__mul__(q) # OK!
Python
converts to
See frac3.py for a full
example of this method
Advanced Example: A6 Pixels
• Image is list of list of RGB
§ But this is really slow
§ Faster: byte buffer (???)
§ Beyond scope of course
• Compromise: Pixels class
§ Has byte buffer attribute
§ Pretends to be list of tuples
§ You can slice/iterate/etc…
• Uses data model to do this
0 1 2 3 4 5 6 7 8 9 10 11 12
0
1
2
3
4
5
6
7
8
9
10
11
12
[(255,255,255), (255,255,255), …]