Kaydet (Commit) e876949f authored tarafından Guido van Rossum's avatar Guido van Rossum

Initial revision

üst 04691fc1
# Complex numbers
from math import sqrt
def complex(re, im):
return Complex().init(re, im)
class Complex:
def init(self, re, im):
self.re = float(re)
self.im = float(im)
return self
def __repr__(self):
return 'complex' + `self.re, self.im`
def __cmp__(a, b):
a = a.__abs__()
b = b.__abs__()
return (a > b) - (a < b)
def __float__(self):
if self.im:
raise ValueError, 'cannot convert complex to float'
return float(self.re)
def __long__(self):
return long(float(self))
def __int__(self):
return int(float(self))
def __abs__(self):
# XXX overflow?
return sqrt(self.re*self.re + self.im*self.im)
def __add__(a, b):
return complex(a.re + b.re, a.im + b.im)
def __sub__(a, b):
return complex(a.re - b.re, a.im - b.im)
def __mul__(a, b):
return complex(a.re*b.re - a.im*b.im, a.re*b.im + a.im*b.re)
def __div__(a, b):
q = (b.re*b.re + b.im*b.im)
re = (a.re*b.re + a.im*b.im) / q
im = (a.im*b.re - b.im*a.re) / q
return complex(re, im)
def __neg__(self):
return complex(-self.re, -self.im)
def test():
a = complex(2, 0)
b = complex(3, 4)
print a, b
print a+b, a-b, a*b, a/b
print b+a, b-a, b*a, b/a
i = complex(0, 1)
print i, i*i, i*i*i, i*i*i*i
j = complex(1, 1)
print j, j*j, j*j*j, j*j*j*j
print abs(j), abs(j*j), abs(j*j*j), abs(j*j*j*j)
print i/-i
test()
# A wrapper around the (optional) built-in class dbm, supporting keys
# and values of almost any type instead of just string.
# (Actually, this works only for keys and values that can be read back
# correctly after being converted to a string.)
def opendbm(filename, mode, perm):
return Dbm().init(filename, mode, perm)
class Dbm:
def init(self, filename, mode, perm):
import dbm
self.db = dbm.open(filename, mode, perm)
return self
def __repr__(self):
s = ''
for key in self.keys():
t = `key` + ': ' + `self[key]`
if s: t = t + ', '
s = s + t
return '{' + s + '}'
def __len__(self):
return len(self.db)
def __getitem__(self, key):
return eval(self.db[`key`])
def __setitem__(self, key, value):
self.db[`key`] = `value`
def __delitem__(self, key):
del self.db[`key`]
def keys(self):
res = []
for key in self.db.keys():
res.append(eval(key))
return res
def has_key(self, key):
return self.db.has_key(`key`)
def test():
d = opendbm('@dbm', 'rw', 0666)
print d
while 1:
try:
key = eval(raw_input('key: '))
if d.has_key(key):
value = d[key]
print 'currently:', value
value = eval(raw_input('value: '))
if value == None:
del d[key]
else:
d[key] = value
except KeyboardInterrupt:
print ''
print d
except EOFError:
print '[eof]'
break
print d
test()
Examples of classes that implement special operators (see class.doc):
Complex.py Complex numbers
Dbm.py Wrapper around built-in dbm, supporting arbitrary values
Range.py Example of a generator: re-implement built-in range()
Rat.py Rational numbers
Vec.py A simple vector class
(For straightforward examples of basic class features, such as use of
methods and inheritance, see the library code -- especially the window
modules are full of them.)
# Example of a generator: re-implement the built-in range function
# without actually constructing the list of values. (It turns out
# that the built-in function is about 20 times faster -- that's why
# it's built-in. :-)
# Wrapper function to emulate the complicated range() arguments
def range(*a):
if len(a) == 1:
start, stop, step = 0, a[0], 1
elif len(a) == 2:
start, stop = a
step = 1
elif len(a) == 3:
start, stop, step = a
else:
raise TypeError, 'range() needs 1-3 arguments'
return Range().init(start, stop, step)
# Class implementing a range object.
# To the user the instances feel like immutable sequences
# (and you can't concatenate or slice them)
class Range:
# initialization -- should be called only by range() above
def init(self, start, stop, step):
if step == 0:
raise ValueError, 'range() called with zero step'
self.start = start
self.stop = stop
self.step = step
self.len = max(0, int((self.stop - self.start) / self.step))
return self
# implement `x` and is also used by print x
def __repr__(self):
return 'range' + `self.start, self.stop, self.step`
# implement len(x)
def __len__(self):
return self.len
# implement x[i]
def __getitem__(self, i):
if 0 <= i < self.len:
return self.start + self.step * i
else:
raise IndexError, 'range[i] index out of range'
# Small test program
def test():
import time, builtin
print range(10), range(-10, 10), range(0, 10, 2)
for i in range(100, -100, -10): print i,
print
t1 = time.millitimer()
for i in range(1000):
pass
t2 = time.millitimer()
for i in builtin.range(1000):
pass
t3 = time.millitimer()
print t2-t1, 'msec (class)'
print t3-t2, 'msec (built-in)'
test()
# Rational numbers
def rat(num, den):
return Rat().init(num, den)
def gcd(a, b):
while b:
a, b = b, a%b
return a
class Rat:
def init(self, num, den):
if den == 0:
raise ZeroDivisionError, 'rat(x, 0)'
g = gcd(num, den)
self.num = num/g
self.den = den/g
return self
def __repr__(self):
return 'rat' + `self.num, self.den`
def __cmp__(a, b):
c = a-b
if c.num < 0:
return -1
if c.num > 0:
return 1
return 0
def __float__(self):
return float(self.num) / float(self.den)
def __long__(self):
return long(self.num) / long(self.den)
def __int__(self):
return int(self.num / self.den)
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
raise TypeError, 'Rat.__coerce__: bad other arg'
def __add__(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):
return rat(a.num*b.num, a.den*b.den)
def __div__(a, b):
return rat(a.num*b.den, a.den*b.num)
def __neg__(self):
return rat(-self.num, self.den)
def test():
print rat(-1L, 1)
print rat(1, -1)
a = rat(1, 10)
print int(a), long(a), float(a)
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(1, 0)
print a+1
print a+1L
print a+1.0
test()
# A simple vector class
def vec(*v):
return apply(Vec().init, v)
class Vec:
def init(self, *v):
self.v = []
for x in v:
self.v.append(x)
return self
def fromlist(self, v):
self.v = []
if type(v) <> type([]):
raise TypeError
self.v = v[:]
return self
def __repr__(self):
return 'vec(' + `self.v`[1:-1] + ')'
def __len__(self):
return len(self.v)
def __getitem__(self, i):
return self.v[i]
def __add__(a, b):
# Element-wise addition
v = []
for i in range(len(a)):
v.append(a[i] + b[i])
return Vec().fromlist(v)
def __sub__(a, b):
# Element-wise subtraction
v = []
for i in range(len(a)):
v.append(a[i] - b[i])
return Vec().fromlist(v)
def __mul__(self, scalar):
# Multiply by scalar
v = []
for i in range(len(self.v)):
v.append(self.v[i]*scalar)
return Vec().fromlist(v)
def test():
a = vec(1, 2, 3)
b = vec(3, 2, 1)
print a
print b
print a+b
print a*3.0
test()
New features of classes
=======================
A class can implement certain operations that are invoked by special
syntax (such as subscription or arithmetic operations) by defining
methods with special names.
Special methods for any type
----------------------------
__repr__(self) --> string
Used by the print statement and conversions (reverse quotes) to
compute the string representation of an object.
__cmp__(self, other) --> int
Used by all comparison operations. Should return -1 if self<other, 0
if self==other, +1 if self>other. Due to limitations in the
interpreter, exceptions raised by comparisons are ignored, and the
objects will be considered equal in this case.
Special methods for sequence and mapping types
----------------------------------------------
__len__(self) --> int
Used by the built-in function len(). Should return the length of the
object, which should be >= 0. Also, an object whose __len__() method
returns 0
__getitem__(self, key) --> value
Used to implement value = self[key]. Note that the special
interpretation of negative keys (if the class wishes to emulate a
sequence type) is up to the __getitem__ method.
__setitem__(self, key, value)
Used to implement self[key] = value. Same note as for __getitem__.
__delitem__(self, key)
Used to implement del self[key]. Same note as for __getitem__.
Special methods for sequence types
----------------------------------
__getslice__(self, i, j) --> sequence
Used to implement self[i:j]. Note that missing i or j are replaced by
0 or len(self), respectively, and len(self) has been added to negative
i or j.
__setslice__(self, i, j, sequence)
Used to implement self[i:j] = value. Same note as for __getslice__.
__delslice__(self, i, j)
Used to implement del self[i:j]. Same note as for __getslice__.
Special methods for numeric types
---------------------------------
__add__, __sub__, __mul__, __div__, __mod__, __divmod__, __pow__,
__lshift__, __rshift__, __and__, __xor__, __or__
Used to implement the binary arithmetic operations (divmod and pow are
called by built-in functions). All have the call pattern
func(self, other) --> number.
__neg__, __pos__, __abs__, __invert__
Used to implement the unary arithmetic operations (-, +, abs and ~).
All have the call pattern func(self) --> number.
__nonzero__(self) --> int
Used to implement boolean testing. An alternative name for this
method is __len__.
__coerce__(self, other) --> (self1, other1) or None
Used to implement "mixed-mode" numeric arithmetic. Either return a
tuple containing self and other converted to some common type, or None
if no way of conversion is known. When the common type would be the
type of other, it is sufficient to return None, since the interpreter
will also ask the other object to attempt a coercion (but sometimes,
if the implementation of the other type cannot be changed, it is
useful to do the conversion to the other type here).
__int__(self) --> int
__long__(self) --> long
__float__(self) --> float
Used to implement the built-in functions int(), long() and float().
Notes
-----
Except for __repr__ and __cmp__, when no appropriate method is
defined, attempts to execute the operation raise an exception. For
__repr__ and __cmp__, the traditional interpretations are used
in this case.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment