adapted to new overloading scheme
This commit is contained in:
parent
74233b34e1
commit
2e61103c0b
|
@ -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
|
||||
|
||||
# complain about int-date
|
||||
def __rsub__( self, other ):
|
||||
raise TypeError, 'Can\'t subtract date from integer'
|
||||
|
||||
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 ):
|
||||
raise TypeError, 'Can\'t subtract date from integer'
|
||||
|
||||
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'
|
||||
|
|
|
@ -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'
|
||||
|
|
Loading…
Reference in New Issue