| prev | Draft Version 555 (Mon Dec 5 17:01:45 2005) | next |
p[1] means “the Y coordinate”"orange"class keywordclass is followed by ":", and introduces blockobject in parenthesespass, this creates a blank objectobj.data to access the data member of obj
obj.x = 3 either:
obj a new member x, and assigns it the value 3, orx with the value 3class point2d(object):
pass
if __name__ == '__main__':
p = point2d()
p.x = 0.0
p.y = 3.0
print "point is", p
print "coordiantes are", p.x, p.y
obj['x'], have obj.xselfobj.meth(arg) is equivalent to:
obj is an instance ofmeth method with obj and arg as arguments__init__
data member as self.data
selfdata is not the same as self.data
data on its own means “a local variable called data”class point2d(object):
# Constructor defines how to create new objects.
def __init__(self):
self.x = 0
self.y = 0
# Get X coordinate.
def getX(self):
return self.x
# Set X coordinate.
def setX(self, newX):
assert newX >= 0
self.x = newX
# Get and set Y coordinate.
def getY(self):
return self.y
def setY(self, newY):
assert newY >= 0
self.y = newY
# Calculate norm.
def norm(self):
return math.sqrt(self.x ** 2 + self.y ** 2)
__init__ constructor sets the point's initial coordinates# Tests.
if __name__ == '__main__':
p = point2d()
assert p.getX() == 0.0
assert p.getY() == 0.0
p.setX(3.0)
p.setY(4.0)
assert p.getX() == 3.0
assert p.getY() == 4.0
assert p.norm() == 5.0
try:
p.setX(-1.0)
assert False
except AssertionError:
pass
p = point2d()
p.setX(9.0)
p.setY(2.0)
print "calling getX directly gives", point2d.getX(p)
calling getX directly gives 9.0
class Queue(object):
'''Implement a queue.'''
def __init__(self):
'''Construct an empty queue.'''
self.data = []
def enq(self, val):
'''Add a new value to the end of the queue.'''
self.data.append(val)
def deq(self):
'''Return the front value of the queue, or raise ValueError if
the queue is empty.'''
if len(self.data) == 0:
raise ValueError, "Can't dequeue from empty queue"
val = self.data[0]
self.data = self.data[1:]
return val
def empty(self):
'''Report whether the queue is empty or not.'''
return len(self.data) == 0
print Queue.__doc__
print Queue.enq.__doc__
print q.deq.__doc__
Implement a queue.
Add a new value to the end of the queue.
Return the front value of the queue, or raise ValueError if
the queue is empty.
raise ValueError instead of using assert when someone tries to dequeue from an empty queuepoint2d.setX and point2d.setY have raised ValueError as well?if __name__ == '__main__':
q = Queue()
assert q.empty()
try:
x = q.deq()
assert False
except ValueError:
pass
q.enq('first')
assert not q.empty()
q.enq('second')
assert q.deq() == 'first'
assert q.deq() == 'second'
assert q.empty()
__init__ is just one example of a special method
__str__
__str__class first(object):
def __init__(self, name):
self.name = name
class second(object):
def __init__(self, name):
self.name = name
def __str__(self):
return 'second/"%s"' % self.name
f = first("orange")
print "first object is", f
s = second("apple")
print "second object is", s
first object is <__main__.first object at 0x401d982c> second object is second/"apple"
obj is an object, len(obj) calls obj.__len__()
Queue to report how long the queue isx in obj is equivalent to obj.__contains__(x)
Queue, but should we?class Queue(object):
def __init__(self):
self.data = []
def enq(self, val):
self.data.append(val)
def deq(self):
if len(self.data) == 0:
raise ValueError, "Can't dequeue from empty queue"
val = self.data[0]
self.data = self.data[1:]
return val
def __len__(self):
return len(self.data)
def empty(self):
return self.__len__() == 0
if __name__ == '__main__':
q = Queue()
q.enq('first')
q.enq('second')
assert len(q) == 2
q.deq()
q.deq()
assert q.empty()
__len__ and one without?Person as:
class Person(object):
'''Represent generic traits of any person.'''
def __init__(self, name, email):
'''Create a new person with a name and an email address.'''
self.name = name
self.email = email
def getName(self):
return self.name
def getEmail(self):
return self.email
Professor:
class Professor(Person):
'''Professors are more than people...'''
def __init__(self, name, email, office):
Person.__init__(self, name, email)
self.office = office
def getOffice(self):
return self.office
Professor(Person) instead of Professor(object)
Professor extends Person instead of the generic built-in object classProfessor's constructor calls Person'sPerson's initialization is done without duplicating codePerson will automatically be reflected in PersonStudent:
class Student(Person):
'''Students are more than people too...'''
def __init__(self, name, email, program):
Person.__init__(self, name, email)
self.program = program
def getProgram(self):
return self.program
if __name__ == '__main__':
tb = Professor('Tycho Brahe', 't.brahe@copenhagen.dk', 'Room 241')
print tb.getName(), tb.getEmail(), tb.getOffice()
jk = Student('Johannes Kepler', 'j.kepler@uraniborg.org', 'B.A.')
print jk.getName(), jk.getEmail(), jk.getProgram()
Tycho Brahe t.brahe@copenhagen.dk Room 241 Johannes Kepler j.kepler@uraniborg.org B.A.
Person.__str__, then override it with more specific definitions in Professor and Student
class Person(object):
def __init__(self, name, email):
self.name = name
self.email = email
...
def __str__(self):
return '%s (%s)' % (self.name, self.email)
class Professor(Person):
def __init__(self, name, email, office):
Person.__init__(self, name, email)
self.office = office
...
def __str__(self):
result = Person.__str__(self)
result += ' Room %s' % self.office
return result
class Student(Person):
def __init__(self, name, email, program):
Person.__init__(self, name, email)
self.program = program
...
def __str__(self):
result = Person.__str__(self)
result += ' Program %s' % self.program
return result
if __name__ == '__main__':
crowd = [
Professor('Tycho Brahe', 't.brahe@copenhagen.dk', 'Room 241'),
Student('Johannes Kepler', 'j.kepler@uraniborg.org', 'B.A.')
]
for person in crowd:
print person
Tycho Brahe (t.brahe@copenhagen.dk) Room Room 241 Johannes Kepler (j.kepler@uraniborg.org) Program B.A.
Shape defines a method area, then obj.area() will return the area of obj without the caller having to know if obj is actually a square or a circleParent.meth returns a string, Child.meth must also return a stringParent.meth returns a non-empty string with at least three vowels, Child.meth must as wellChild.meth must satisfy all the post-conditions of Parent.meth, and may impose moreChild.meth's possible output is a subset of Parent.meth'sParent.meth will continue to work if given an instance of Child insteadChild.meth may ignore some of Parent.meth's pre-conditions, but may not impose moreChild.meth accepts everything thatParent.meth did, and possibly moreParent.meth correctly is guaranteed to call Child.meth correctly tooclass block belong to the class as a wholeclass Counter(object):
num = 0 # Number of Counter objects created.
def __init__(self, name):
Counter.num += 1
self.name = name
if __name__ == '__main__':
print 'initial count', Counter.num
first = Counter('first')
print 'after creating first object', Counter.num
second = Counter('second')
print 'after creating second object', Counter.num
initial count 0 after creating first object 1 after creating second object 2
"+" is just a shorthand for a function that takes two arguments__add__, it takes precedence over the built-in “function”
x + y calls x.__add__(y)2 + x and x + 2 don't always do the same thing__radd__ instead of __add__
x has an __add__ method, call thaty has an __radd__ method, call thatv after:
v = SparseVector() # all values initialized to 0.0 v[27] = 1.0 # length is now 28 v[43] = 1.0 # length is now 44 v[43] = 0.0 # is the length still 44, or 28?
class SparseVector(object):
'''Implement a sparse vector. If a value has not been set
explicitly, its value is zero.'''
def __init__(self):
'''Construct a sparse vector with all zero entries.'''
self.values = {}
def __len__(self):
'''The length of a vector length is the largest index ever seen.'''
if len(self.values):
return max(self.values.keys())
return 0
[] is just a binary operator tooobj[index] is implemented as obj.__getitem__(index)obj[index] = value is obj.__setitem(index, value) def __getitem__(self, key):
'''Return an explicit value, or 0.0 if none has been set.'''
if key in self.values:
return self.values[key]
return 0.0
def __setitem__(self, key, value):
'''Assign a new value to a vector entry.'''
self.values[key] = value
"*") is usually called other def __mul__(self, other):
'''Calculate cross product of a sparse vector with something else.'''
result = 0.0
for k in self.values.keys():
result += self.values[k] * other[k]
return result
def __rmul__(self, other):
return self.__mul__(other)
__rmul__ = __mul__ makes __rmul__ point to the same code as __mul__
def __add__(self, other):
'''Add something to a sparse vector.'''
# Initialize result with all non-zero values from this vector.
result = SparseVector()
result.values.update(self.values)
# If the other object is also a sparse vector, add non-zero values.
if isinstance(other, SparseVector):
for k in other.values.keys():
result[k] = result[k] + other[k]
# Otherwise, use brute force.
else:
for i in range(len(other)):
result[i] = result[i] + other[i]
return result
# Right-hand add does the same thing as left-hand add.
__radd__ = __add__
if __name__ == '__main__':
x = SparseVector()
x[1] = 1.0
x[3] = 3.0
x[5] = 5.0
print 'len(x)', len(x)
for i in range(len(x)):
print '...', i, x[i]
y = SparseVector()
y[1] = 10.0
y[2] = 20.0
y[3] = 30.0
print 'x + y', x + y
print 'y + x', y + x
print 'x * y', x * y
print 'y * x', y * x
z = [0.0, 0.1, 0.2, 0.3, 0.4, 0.5]
print 'x + z', x + z
print 'x * z', x * z
print 'z + x', z + x
| prev | Copyright © 2005, Python Software Foundation. See License for details. | next |