promoting [] by superclass?

Terry Reedy tjreedy at udel.edu
Wed Jun 9 12:47:31 CEST 2004


"Jim Newton" <jimka at rdrop.com> wrote in message
news:2imqj3Fopq78U1 at uni-berlin.de...
> So it would be great if Pair(1,2,3,4,5) would
> return [1, [2, [3, [5, nil]]]] with all the bracketed
> lists promoted to class Pair.  Can that be done
> with the __init__ function?  currently i'm doing that
> with a seperate function which takes any sequence as its argument.
....separate...
> Basically i'd like the Pair.__init__ in the case of Pair(1,2,3,4,5),
> to set self[0]=1, and self[1] = Pair(2,3,4,5) in some iterative
> way.

If you use Pair.__init__, I believe the buildup has to be top-down
recursive.  Botton-up iteration would require a factory function.  See
below.

> Robert Brewer wrote:
> > TypeError saying that __init__ takes a different number of arguments.
If
> > you want to override __init__, it should be written:
> >
> >>>>class x1(list):
> >
> > ... def __init__(self, sequence):
> > ... pass

In order for Pair() to work like list(), sequence must be optional.  I
default it to None since that works.  While default [] works in this case,
it is not needed and is often a bug.  First a small test to verify what
init gets:

>>> class Pair(list):
...   def __init__(self, seq=None):
...     print self, seq
...
>>> l = Pair([1,2,3])
[] [1, 2, 3]

Since list (and Pair) are mutable, new creates an empty object, which
__init__ must fill in.  The parameters of __init__ are the empty object,
conventionally called 'self', and the sequence to be used to fill it in.

Now for real:

class Pair(list):
    def __init__(self, seq=None):
        if seq:
            self.append(seq[0])
            self.append(Pair(seq[1:]))

p = Pair([1,2,3])
>>>print  p
[1, [2, [3, []]]]
>>> while p:
...   print type(p)
...   p = p[1]
...
<class '__main__.Pair'>
<class '__main__.Pair'>
<class '__main__.Pair'>
>>> p, type(p)
([], <class '__main__.Pair'>)
>>> p2=Pair([])
>>> p == p2
1

Is ths what you wanted?
Alternatively, if Pair is to be initialized with pairs, as might seem
sensible:

class Pair2(list):
    def __init__(self, pair=None):
        if pair:
            if len(pair) == 2:
                self.append(pair[0])
                self.append(pair[1])
            else: raise ValueError('nonempty Pair must be initialized with
pair')

then build up with iteration:

def makePair(seq): # this could be a Pair staticmethod
    p = Pair2()
    while seq:
        p = Pair2((seq.pop(),p))
    return p

>>> p2 = makePair([1,2,3])
>>> p2
[1, [2, [3, []]]]
>>> while p2: print type(p2); p2 = p2[1]
...
<class '__main__.Pair2'>
<class '__main__.Pair2'>
<class '__main__.Pair2'>

Terry J. Reedy







More information about the Python-list mailing list