diff options
-rwxr-xr-x | Demo/classes/Dates.py | 63 | ||||
-rwxr-xr-x | Demo/classes/Rat.py | 48 |
2 files changed, 51 insertions, 60 deletions
diff --git a/Demo/classes/Dates.py b/Demo/classes/Dates.py index 4e8bbf7..7f55d24 100755 --- a/Demo/classes/Dates.py +++ b/Demo/classes/Dates.py @@ -16,7 +16,7 @@ # Date objects support one visible method, date.weekday(). This returns # the day of the week the date falls on, as a string. # -# Date objects also have 4 (conceptually) read-only data attributes: +# Date objects also have 4 read-only data attributes: # .month in 1..12 # .day in 1..31 # .year int or long int @@ -33,6 +33,11 @@ # Tim Peters tim@ksr.com # not speaking for Kendall Square Research Corp +# Adapted to Python 1.1 (where some hacks to overcome coercion are unnecessary) +# by Guido van Rossum + +# vi:set tabsize=8: + _MONTH_NAMES = [ 'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December' ] @@ -81,6 +86,7 @@ def _num2date( n ): # return date with ordinal n raise TypeError, 'argument must be integer: ' + `type(n)` ans = Date(1,1,1) # arguments irrelevant; just getting a Date obj + del ans.ord, ans.month, ans.day, ans.year # un-initialize it ans.ord = n n400 = (n-1)/_DI400Y # # of 400-year blocks preceding @@ -93,7 +99,7 @@ def _num2date( n ): # return date with ordinal n year, n = year + more, int(n - dby) try: year = int(year) # chop to int, if it fits - except ValueError: pass + except (ValueError, OverflowError): pass month = min( n/29 + 1, 12 ) dbm = _days_before_month( month, year ) @@ -118,6 +124,12 @@ class Date: self.month, self.day, self.year = month, day, year self.ord = _date2num( self ) + # don't allow setting existing attributes + def __setattr__( self, name, value ): + if self.__dict__.has_key(name): + raise AttributeError, 'read-only attribute ' + name + self.__dict__[name] = value + def __cmp__( self, other ): return cmp( self.ord, other.ord ) @@ -132,52 +144,27 @@ class Date: self.day, _MONTH_NAMES[self.month-1] ) + `self.year` - # automatic coercion is a pain for date arithmetic, since e.g. - # date-date and date-int mean different things. So, in order to - # sneak integers past Python's coercion rules without losing the info - # that they're really integers (& not dates!), integers are disguised - # as instances of the derived class _DisguisedInt. That this works - # relies on undocumented behavior of Python's coercion rules. - def __coerce__( self, other ): - if type(other) in _INT_TYPES: - return self, _DisguisedInt(other) - # if another Date, fine - if type(other) is type(self) and other.__class__ is Date: - return self, other - - # Python coerces int+date, but not date+int; in the former case, - # _DisguisedInt.__add__ handles it, so we only need to do - # date+int here + # Python 1.1 coerces neither int+date nor date+int def __add__( self, n ): if type(n) not in _INT_TYPES: raise TypeError, 'can\'t add ' + `type(n)` + ' to date' return _num2date( self.ord + n ) + __radd__ = __add__ # handle int+date - # Python coerces all of int-date, date-int and date-date; the first - # case winds up in _DisguisedInt.__sub__, leaving the latter two - # for us + # Python 1.1 coerces neither date-int nor date-date def __sub__( self, other ): - if other.__class__ is _DisguisedInt: # date-int - return _num2date( self.ord - other.ord ) + if type(other) in _INT_TYPES: # date-int + return _num2date( self.ord - other ) else: return self.ord - other.ord # date-date - def weekday( self ): - return _num2day( self.ord ) - -# see comments before Date.__add__ -class _DisguisedInt( Date ): - def __init__( self, n ): - self.ord = n - - # handle int+date - def __add__( self, other ): - return other.__add__( self.ord ) - # complain about int-date - def __sub__( self, other ): + def __rsub__( self, other ): raise TypeError, 'Can\'t subtract date from integer' + def weekday( self ): + return _num2day( self.ord ) + def today(): import time local = time.localtime(time.time()) @@ -189,9 +176,7 @@ def test( firstyear, lastyear ): b = Date(9,30,1914) if `a` != 'Tue 30 Sep 1913': raise DateTestError, '__repr__ failure' - if (not a < b) or a == b or a > b or b != b or \ - a != 698982 or 698982 != a or \ - (not a > 5) or (not 5 < a): + if (not a < b) or a == b or a > b or b != b: raise DateTestError, '__cmp__ failure' if a+365 != b or 365+a != b: raise DateTestError, '__add__ failure' diff --git a/Demo/classes/Rat.py b/Demo/classes/Rat.py index d10e4df..7553745 100755 --- a/Demo/classes/Rat.py +++ b/Demo/classes/Rat.py @@ -1,7 +1,10 @@ # Rational numbers +from types import * def rat(num, den): + if type(num) == FloatType or type(den) == FloatType: + return num/den return Rat(num, den) @@ -16,12 +19,21 @@ class Rat: def __init__(self, num, den): if den == 0: raise ZeroDivisionError, 'rat(x, 0)' - g = gcd(num, den) + if type(den) == FloatType or type(num) == FloatType: + g = float(den) + else: + g = gcd(num, den) self.num = num/g self.den = den/g def __repr__(self): - return 'rat' + `self.num, self.den` + return 'Rat(%s, %s)' % (self.num, self.den) + + def __str__(self): + if self.den == 1: + return str(self.num) + else: + return '%s/%s' % (self.num, self.den) def __cmp__(a, b): c = a-b @@ -42,29 +54,23 @@ class Rat: def __coerce__(a, b): t = type(b) - if t == type(0): - return a, rat(b, 1) - if t == type(0L): - return a, rat(b, 1L) - if t == type(0.0): - return a.__float__(), b - if t == type(a) and a.__class__ == b.__class__: + if t == IntType: + return a, Rat(b, 1) + if t == LongType: + return a, Rat(b, 1L) + if t == FloatType: + return a, Rat(b, 1.0) + if t == InstanceType and a.__class__ == b.__class__: return a, b raise TypeError, 'Rat.__coerce__: bad other arg' def __add__(a, b): - if type(b) <> type(a): - a, b = a.__coerce__(b) - return a + b return rat(a.num*b.den + b.num*a.den, a.den*b.den) def __sub__(a, b): return rat(a.num*b.den - b.num*a.den, a.den*b.den) def __mul__(a, b): - if type(b) <> type(a): - a, b = a.__coerce__(b) - return a * b return rat(a.num*b.num, a.den*b.den) def __div__(a, b): @@ -75,21 +81,21 @@ class Rat: def test(): - print rat(-1L, 1) - print rat(1, -1) - a = rat(1, 10) + print Rat(-1L, 1) + print Rat(1, -1) + a = Rat(1, 10) print int(a), long(a), float(a) - b = rat(2, 5) + b = Rat(2, 5) l = [a+b, a-b, a*b, a/b] print l l.sort() print l - print rat(0, 1) + print Rat(0, 1) print a+1 print a+1L print a+1.0 try: - print rat(1, 0) + print Rat(1, 0) raise SystemError, 'should have been ZeroDivisionError' except ZeroDivisionError: print 'OK' |