Spring Semester 2007 |

Lecture Eight:

Let's implement additional behavior for fractions. | Here's how a fraction can add (with another fraction). |

class fraction(object): def gcd(a, b): m = max(abs(a), abs(b)) n = min(abs(a), abs(b)) if n == 0: return 0 else: d = n while not (m % d == 0 and n % d == 0): d -= 1 return d gcd = staticmethod(gcd) def __init__(self, num, den): self.num = num / fraction.gcd(num, den) self.den = den / fraction.gcd(num, den) def __str__(self): return str(self.num) + "/" + str(self.den) def add(self, other): return fraction(self.den * other.num + self.num * other.den, \ self.den * other.den)

Here's an example, too. | One third plus two thirds should be equal to one. |

>>> a = fraction(2,3) >>> b = fraction(1,3) >>> a.add(b) <__main__.fraction object at 0x00D55150> >>> print a.add(b) 1/1 >>>

The code changes now to accomodate private instance variables. | Note that we end up making more changes than we would first expect. |

class fraction(object): def gcd(a, b): m = max(abs(a), abs(b)) n = min(abs(a), abs(b)) if n == 0: return 0 else: d = n while not (m % d == 0 and n % d == 0): d -= 1 return d gcd = staticmethod(gcd) def __init__(self, num, den): self.__num = num / fraction.gcd(num, den) self.__den = den / fraction.gcd(num, den) def __str__(self): return str(self.__num) + "/" + str(self.__den) def add(self, other): return fraction(self.__den * other.getNum() + self.__num * other.getDen(), \ self.__den * other.getDen()) def getNum(self): return self.__num def getDen(self): return self.__den

Why is that necessary? | In this case it isn't, but how acess to the other fraction's numerator and denominator should be read only, no? |

>>> >>> a = fraction(2,3) >>> a.__num Traceback (most recent call last): File "", line 1, in a.__num AttributeError: 'fraction' object has no attribute '__num' >>> b = fraction(1,3) >>> a.add(b) <__main__.fraction object at 0x00D55EF0> >>> print a.add(b) 1/1 >>> print fraction(2,6).add(fraction(5,3)) 2/1 >>> print fraction(2,6) 1/3 >>> print fraction(5,3) 5/3 >>>

I see: some sort of hygienic perspective. | Profilaxy, if you want. |

So access to private variables is completely closed outside the class? | No, not really; Python conventions only mean to discourage this type of access. |

>>> a._fraction__num 2 >>> a = fraction(2,3) >>> a._fraction__num 2 >>> a._fraction__den 3 >>>

Same goes for methods. | So we're now ready for a review and the new program. |

Here's the critter program from Dawson's book. | What's in this program that we didn't discuss? |

Properties. | How can you quickly explain those? |

It's only syntax, nothing deep. | Show me. |

Here's come code that uses (defines) properties. | How does this work? |

class critter(object): def __init__(self): self.__a = "first secret" self.__b = "second secret" def get_a(self): return self.__a def get_b(self): return self.__b def set_b(self, value): self.__b = value a = property(get_a) b = property(get_b, set_b)

Here's how it works. | I see; just as you said, syntactic sugar, nothing more. |

>>> x = critter() >>> x.__a Traceback (most recent call last): File "<pyshell#127>", line 1, inx.__a AttributeError: 'critter' object has no attribute '__a' >>> x._critter__a 'first secret' >>> x._critter__a = "changed once" >>> x._critter__a 'changed once' >>> x.a 'changed once' >>> x.a = 'changed again' Traceback (most recent call last): File "<pyshell#132>", line 1, in x.a = 'changed again' AttributeError: can't set attribute >>> x.b 'second secret' >>> x.b = 'changed once' >>> x.b 'changed once' >>> x.__b Traceback (most recent call last): File "<pyshell#136>", line 1, in x.__b AttributeError: 'critter' object has no attribute '__b' >>> x._critter__b 'changed once' >>> x._critter__b = 'changed again' >>> x.b 'changed again' >>>

Here's one more example, illustrating static variables. | Good. I think that's enough for today. |

class critter(object): total = 0 def __init__(self): critter.total += 1 def test(): c = [] for i in range(10): c.append(critter()) print critter.total

Same here. | See you in lab. |

Files for the next chapter (lab this week): | We'll cover them in this order. |

alien_blaster.py playing_cards.py playing_cards2.py playing_cards3.py games.py simple_game.py cards.py blackjack.py