how to do proper subclassing?

Peter Otten __peter__ at web.de
Wed Aug 4 04:41:46 EDT 2004


Jonas Koelker wrote:

> I'm new to this list (/me welcomes himself).

Jonas, I suggest that you post follow-ups vaguely on topic on c.l.py. That
gives you the chance for answers that I (for example) don't know about or
care to give as well as corrections or a second opinion.

[Jonas via email]

> > >>> class Perm(list):
> >
> > ...     def __init__(self, n):
> > ...             list.__init__(self, range(n))
> > ...     def __call__(self, i, k):
> > ...             self[i], self[k] = self[k], self[i]
> > ...             return self
> > ...
> >
> > >>> p = Perm(5)
> > >>> p
> >
> > [0, 1, 2, 3, 4]
> >
> > >>> p(0,4)(2,4)(0,1)(2,3)(1,2)
> >
> > [1, 3, 4, 0, 2]
> >
> > >>> p[1:2]
> >
> > [3]
> >
> > >>> p[1:3]
> >
> > [3, 4]
>
> thanks, this looks about right (slaps himself on the
> forehead - "you DO know how init works!")... :]
>
> also, p(0,4)(2,4)(0,1)(2,3)(1,2) looks really neat and
> math'ish :)
>
> > Just in case you need it later, there is a special
> > method for every operator, e. g. __getitem__() for
> >obj[sliceOrIndex], __mul__() for multiplication etc.
>
> Yeah, I knew that. I might make __int__() convert the
> perm to a ranking number in linear time. See

My mentioning of special methods doesn't mean that I think they are always
the best choice. I would prefer both p.rank() and rank(p) over int(p).

> http://www.cs.uvic.ca/~ruskey/Publications/RankPerm.html
>
> .. don't worry, I can implement it myself.

Don't worry, I won't :-)

> btw, if I want to set the "list part" of the perm, how
> do I do that?

p[:] =  [1, 2, 3, 4, 5]
p[:2] = p[1], p[0]
p[2] = [99]

If you want to ensure that the permutation is still valid after assignment
you have to write your own __setitem__() method.

> p = [4,0,3,2,1] would turn p into a list.
> p = perm(5)(0,4)(2,4)(0,1)(2,3)(1,2) is valid (right?)
> but time consuming.

That was just for fun... most likely faster than

while p != [4,0,3,2,1]: random.shuffle(p)

> I'd say it'd be easier/better to implement it as:
> >>> class Perm(list):
>
> ...     def __init__(self, n):
> ...             list.__init__(self, n)

The good news: if __init__() does nothing but call the base class'
__init__(), you need not write one at all.

> ...     def __call__(self, i, k):
> ...             self[i], self[k] = self[k], self[i]
> ...             return self
>
> >>> p = Perm([4, 0, 3, 2, 1])
>
> ... anyways, thanks :)

You're welcome.

Peter




More information about the Python-list mailing list