prev | Draft Version 555 (Thu Dec 1 09:18:27 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.x
self
obj.meth(arg)
is equivalent to:
obj
is an instance ofmeth
method with obj
and arg
as arguments__init__
data
member as self.data
self
data
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 Person
Student
:
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 |