[Tutor] working with new classes
C Smith
smichr at hotmail.com
Thu Mar 10 00:17:59 CET 2005
Thanks to Sean and Kent for replies. I found a site that provided some
good examples, too, at
http://www.cafepy.com/articles/python_attributes_and_methods/
ch03s02.html
Here's a blurb from the title page:
---- wep page excerpt
Shalabh Chaturvedi
Copyright © 2004 Shalabh Chaturvedi
This book is part of a series:
Python Types and Objects
Python Attributes and Methods [you are here]
----
After playing with this for a while I get the feeling that trying to
create an alternate access for the list is not the way to go. I was
able to define the following methods with success...
###
class Ring(list):
def __init__(self,l):
list.__init__(self,l)
self._zero=0
def turn(self,incr=1):
self._zero+=incr
def __getitem__(self,i):
if type(i)==int:
return list.__getitem__(self,(i-self._zero)%len(self))
else:
return [list.__getitem__(self,(k-self._zero)%len(self)) for k in
range(i.start,i.stop,i.step)]
def __setitem__(self,i,v):
list.__setitem__(self,(i-self._zero)%len(self),v)
def __getslice__(self,i,j):
return
list.__getslice__(self,(i-self._zero)%len(self),(j-
self._zero)%len(self))
def __setslice__(self,i,j,v):
list.__setslice__(self,(i-self._zero)%len(self),(j-
self._zero)%len(self),v)
def __repr__(self):
return repr([self[i] for i in range(len(self))])
###
..but then something like pop(3) pops the original element not the
element in the 3rd position of the turned list:
###
>>> l=Ring(range(10))
>>> l.turn(5)
>>> print l
[5, 6, 7, 8, 9, 0, 1, 2, 3, 4]
>>> l.pop(3); print l
[5, 6, 7, 8, 9, 0, 1, 2, 4] #I wanted the 8 to go
###
So in the absence of being able to redefine in the class the way that
indices should be computed (like the way that your own cmp function can
be supplied for the sort method) it seems best to use the existing
structure and either access the list by passing it indices which have
been remapped:
###
>>> def ring_index(i):
return (i-ring_zero)%ring_length
>>> l = range(10)
>>> ring_length = len(l)
>>> ring_zero = 3 #does a virtual shift to the right 3 elements
>>> print l[ring_index(0)]
7
###
But this will only help you look at individual entries and slices that
don't go across the boundaries of the list.
Alternatively, the list class can be appended with helpers like 'turn'
and 'segment' which can actually turn the "ring" and remove a piece
from it without worrying about the endpoint:
###
>>> class ring(list):
def turn(self, incr=1):
incr%=len(self)
self[:] = self[incr:]+self[:incr]
def segment(self, i, length, incr=1):
length=min(len(self),length)
if i+length>len(self):
return self[i::incr]+self[(length-i)%incr:i+length-len(self):incr]
>>> l=ring(range(20)); l.turn(3); print l
[3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 0, 1, 2]
>>> >>> l.segment(17,5,3) #start at 17, length of 5, stride 3
[0, 3]
###
This is my first intoduction to the new class modifications...initially
it seems nice to be able to wrap your methods up into a class like this
rather than creating dangling functions in one's program.
/c
More information about the Tutor
mailing list