Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Python > RE: promoting [] by superclass?

Reply
Thread Tools

RE: promoting [] by superclass?

 
 
Robert Brewer
Guest
Posts: n/a
 
      06-08-2004
Jim Newton wrote:
> this is interesting. I though that if you passed
> an argument to your class factory function, it would call
> the __init__ with that argument.
>
> class x1(list):
> def __init__(y):
> pass
>
> class x2(list):
> pass
>
> what does x1([]) do and what does x2([]) do?


x1([]) first calls x1.__new__, but since you're not overriding that, it
moves up the class heirarchy to the next superclass, which is 'list',
and calls list.__new__(cls, sequence). Notice that there are two
arguments to this method. That method is written in such a way that the
result is of type 'cls' (in your example, cls == x1). So when this
method returns, we've got an object of type 'x1'.

Then x1.__init__ gets called, passing it the new object and the
'sequence' arg. However, you've overridden list.__init__; moreover, it
doesn't have the same number of arguments as __new__ did, so you get a
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
....
>>> x1([])

[]
>>> type(x1([]))

<class '__main__.x1'>

Now, that only works if you wish to keep the same signature (arguments).
If you want to provide another argument to the class instantiation, you
need to override both __new__ and __init__ so that their argument lists
"match":

>>> class x1(list):

.... def __new__(cls, sequence=[], maxlen=5):
.... return list.__new__(cls, sequence)
.... def __init__(self, sequence=[], maxlen=5):
.... self.maxlen = maxlen
....
>>> x1([])

[]
>>> type(x1([]))

<class '__main__.x1'>
>>> x1([], 7)

[]
>>> x1([], 7).maxlen

7

x2 doesn't override anything, so the default list.* methods get called
for all operations. Remember, though, that list.__new__ produces an
object whose type is the subclass automatically, without overriding;
therefore:

>>> class x2(list): pass

....
>>> type(x2([]))

<class '__main__.x2'>


Hope that helps!

Robert Brewer
MIS
Amor Ministries
http://www.velocityreviews.com/forums/(E-Mail Removed)

 
Reply With Quote
 
 
 
 
Jim Newton
Guest
Posts: n/a
 
      06-08-2004
i see, that does indeed help a lot. So from what you are saying,
it is impossible to have the class name work as both a factory
function and a casting function. I must decide whether i want
Pair( [] ) to build a linked list of its arguments, or simply
to do the class promotion, but it cannot be smart enough to
do both.

So the next best thing would be to have a cast funcion which
calls list().

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.

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.


def seq2pair(seq):
new = Pair()
for index in xrange( len(seq), 0, -1):
new = new.cons(seq[index - 1])
return new

class Pair(list):

...

# x = (cons x list)
# ==> x = list.cons(x)
def cons(self, car):
new = Pair()
new.append(car)
new.append(self)
return new



Robert Brewer wrote:
> Jim Newton wrote:
>
>>this is interesting. I though that if you passed
>>an argument to your class factory function, it would call
>>the __init__ with that argument.
>>
>>class x1(list):
>> def __init__(y):
>> pass
>>
>>class x2(list):
>> pass
>>
>>what does x1([]) do and what does x2([]) do?

>
>
> x1([]) first calls x1.__new__, but since you're not overriding that, it
> moves up the class heirarchy to the next superclass, which is 'list',
> and calls list.__new__(cls, sequence). Notice that there are two
> arguments to this method. That method is written in such a way that the
> result is of type 'cls' (in your example, cls == x1). So when this
> method returns, we've got an object of type 'x1'.
>
> Then x1.__init__ gets called, passing it the new object and the
> 'sequence' arg. However, you've overridden list.__init__; moreover, it
> doesn't have the same number of arguments as __new__ did, so you get a
> 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
> ...
>
>>>>x1([])

>
> []
>
>>>>type(x1([]))

>
> <class '__main__.x1'>
>
> Now, that only works if you wish to keep the same signature (arguments).
> If you want to provide another argument to the class instantiation, you
> need to override both __new__ and __init__ so that their argument lists
> "match":
>
>
>>>>class x1(list):

>
> ... def __new__(cls, sequence=[], maxlen=5):
> ... return list.__new__(cls, sequence)
> ... def __init__(self, sequence=[], maxlen=5):
> ... self.maxlen = maxlen
> ...
>
>>>>x1([])

>
> []
>
>>>>type(x1([]))

>
> <class '__main__.x1'>
>
>>>>x1([], 7)

>
> []
>
>>>>x1([], 7).maxlen

>
> 7
>
> x2 doesn't override anything, so the default list.* methods get called
> for all operations. Remember, though, that list.__new__ produces an
> object whose type is the subclass automatically, without overriding;
> therefore:
>
>
>>>>class x2(list): pass

>
> ...
>
>>>>type(x2([]))

>
> <class '__main__.x2'>
>
>
> Hope that helps!
>
> Robert Brewer
> MIS
> Amor Ministries
> (E-Mail Removed)
>


 
Reply With Quote
 
 
 
 
Terry Reedy
Guest
Posts: n/a
 
      06-09-2004

"Jim Newton" <(E-Mail Removed)> wrote in message
news:(E-Mail Removed)...
> 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




 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Advice on promoting my website Walter HTML 15 12-03-2005 06:03 AM
About promoting your website, something totally new: check this out contactgreg@hotmail.com HTML 3 11-21-2005 08:29 PM
Demoting and Promoting Serialised Objects Roedy Green Java 4 07-10-2005 04:34 AM
Short URL for promoting Firefox/Thunderbird Ewoud Dronkert Firefox 2 10-04-2004 03:27 PM
Which is the best site/tools for announcing/promoting web pages ? Wladimir Borsov HTML 1 08-10-2004 02:51 PM



Advertisments