
July 18th, 2005, 10:56 PM
| | | Style guide for subclassing built-in types?
Please see the following code:
--------------------------------
class rev_wrap(object):
def __init__(self,l):
self.l=l
def __getitem__(self,i):
return self.l[-i-1]
class rev_subclass(list):
def __getitem__(self,i):
return list.__getitem__(self,-i-1)
if __name__=='__main__':
l=rev_wrap([1,2,3])
assert l[0]==3
assert list(l)==[3,2,1]
l=rev_subclass([1,2,3])
assert l[0]==3
assert list(l)==[3,2,1]
I know there is "reversed" and "reverse" but that's not the point. The
code fails at the last line.
Now that UserList is deprecated(not recommended) I suppose subclassing
built-in types are preferable than wrapping them. How do I properly
change the behaviours of built-in types? I think I have to override
__iter__ and next to pass the last line. Is it a good style? If so,
what is the most recommended way of implementing them?
Thank you in advance.
Jane | 
July 18th, 2005, 10:56 PM
| | | Re: Style guide for subclassing built-in types?
Jane Austine wrote:[color=blue]
> Please see the following code:
> --------------------------------
> class rev_wrap(object):
> def __init__(self,l):
> self.l=l
> def __getitem__(self,i):
> return self.l[-i-1]
>
> class rev_subclass(list):
> def __getitem__(self,i):
> return list.__getitem__(self,-i-1)
>
> if __name__=='__main__':
> l=rev_wrap([1,2,3])
> assert l[0]==3
> assert list(l)==[3,2,1]
>
> l=rev_subclass([1,2,3])
> assert l[0]==3
> assert list(l)==[3,2,1][/color]
Oh... I forgot one. assert l==[3,2,1] at this point doesn't pass
either. "print l" outputs the wrong one([1,2,3]) as well. | 
July 18th, 2005, 10:56 PM
| | | Re: Style guide for subclassing built-in types?
I guess print is using the __repr__ (or __str__ ?) methods of lsit -
which you will need to override as well.
Regards,
Fuzzy http://www.voidspace.org.uk/python/index.shtml | 
July 18th, 2005, 10:56 PM
| | | Re: Style guide for subclassing built-in types?
Fuzzyman wrote:[color=blue]
> I guess print is using the __repr__ (or __str__ ?) methods of lsit -
> which you will need to override as well.
>
> Regards,
>
> Fuzzy
> http://www.voidspace.org.uk/python/index.shtml[/color]
Thank you but the problem is that I have to express my intention in
duplicate places -- __iter__(along with "next"), __str__, __eq__ and so
on.
p.s. the reason I'm not sticking to reversed or even reverse : suppose
the size of the list is huge. | 
July 18th, 2005, 10:56 PM
| | | Re: Style guide for subclassing built-in types? janeaustine50@hotmail.com wrote:[color=blue]
> p.s. the reason I'm not sticking to reversed or even reverse : suppose
> the size of the list is huge.[/color]
Reversed is an iterator - it does NOT copy the list. In other words, reversed
already does pretty much what you want.
Cheers,
Nick.
--
Nick Coghlan | ncoghlan@email.com | Brisbane, Australia
--------------------------------------------------------------- http://boredomandlaziness.skystorm.net | 
July 18th, 2005, 10:56 PM
| | | Re: Style guide for subclassing built-in types? janeaustine50@hotmail.com wrote:[color=blue]
> Fuzzyman wrote:[color=green]
> > I guess print is using the __repr__ (or __str__ ?) methods of lsit[/color][/color]
-[color=blue][color=green]
> > which you will need to override as well.
> >
> > Regards,
> >
> > Fuzzy
> > http://www.voidspace.org.uk/python/index.shtml[/color]
>
> Thank you but the problem is that I have to express my intention in
> duplicate places -- __iter__(along with "next"), __str__, __eq__ and[/color]
so[color=blue]
> on.
>[/color]
If you are sublassing the built in types I guess you will have to
change all methods that have changed..
an alternative wuld be to not subclass object and override __getattr__
:
class rev_wrap:
def __init__(self,l):
self.l=l
def __getitem__(self,i):
return self.l[-i-1]
def __getattr__(self, attr):
return getattr(self.l, attr)
Regards,
Fuzzy http://www.voidspace.org.uk/python/index.shtml
[color=blue]
> p.s. the reason I'm not sticking to reversed or even reverse :[/color]
suppose[color=blue]
> the size of the list is huge.[/color] | 
July 18th, 2005, 10:56 PM
| | | Re: Style guide for subclassing built-in types? janeaustine50@hotmail.com wrote:[color=blue]
> p.s. the reason I'm not sticking to reversed or even reverse : suppose
> the size of the list is huge.[/color]
reversed() returns an iterator so list size shouldn't be an issue.
What problem are you actually trying to solve?
Kent
[color=blue]
>[/color] | 
July 18th, 2005, 10:56 PM
| | | Re: Style guide for subclassing built-in types?
Kent Johnson wrote:[color=blue]
> janeaustine50@hotmail.com wrote:[color=green]
> > p.s. the reason I'm not sticking to reversed or even reverse :[/color][/color]
suppose[color=blue][color=green]
> > the size of the list is huge.[/color]
>
> reversed() returns an iterator so list size shouldn't be an issue.
>
> What problem are you actually trying to solve?
>
> Kent
>[/color]
Oh, you are right.
Actually, it's more complicated than simple reversion. The list order
should be somewhat "twisted" and the list is big.
For example,
[1,2,3,4,5,6,7,8,9,10]
--> [10,9,8,7,6,1,2,3,4,5]
so __getitem__(self,i) => __getitem__(self,-i-1) if i<len(size)/2,
otherwise __getitem__(self,i-len(size)/2)
I'd like to have TwistedList class that takes in an original list and
pretends as if it is twisted actually. However, I have to have
duplicate codes here and there to make it act like a "list", say assert
twisted_list == [10,9,...] and for each in twisted_list and etc. | 
July 18th, 2005, 10:57 PM
| | | Re: Style guide for subclassing built-in types? janeaustine50@hotmail.com wrote:[color=blue]
> Kent Johnson wrote:
>[color=green]
>>janeaustine50@hotmail.com wrote:
>>[color=darkred]
>>>p.s. the reason I'm not sticking to reversed or even reverse :[/color][/color]
>
> suppose
>[color=green][color=darkred]
>>>the size of the list is huge.[/color]
>>
>>reversed() returns an iterator so list size shouldn't be an issue.
>>
>>What problem are you actually trying to solve?
>>
>>Kent
>>[/color]
>
>
> Oh, you are right.
>
> Actually, it's more complicated than simple reversion. The list order
> should be somewhat "twisted" and the list is big.
>
> For example,
>
> [1,2,3,4,5,6,7,8,9,10]
>
> --> [10,9,8,7,6,1,2,3,4,5]
>
> so __getitem__(self,i) => __getitem__(self,-i-1) if i<len(size)/2,
> otherwise __getitem__(self,i-len(size)/2)
>
> I'd like to have TwistedList class that takes in an original list and
> pretends as if it is twisted actually. However, I have to have
> duplicate codes here and there to make it act like a "list", say assert
> twisted_list == [10,9,...] and for each in twisted_list and etc.
>[/color]
If you want a twisted 'view' of an existing list, then a wrapper makes most sense.
If, however, you only need the twisted version, why not simply override
list.__init__ (and extend, append etc... as required):
[color=blue][color=green][color=darkred]
>>> class rev_list(list):[/color][/color][/color]
... def __init__(self, iterable):
... list.__init__(self, iterable[::-1])
...[color=blue][color=green][color=darkred]
>>> l = rev_list([1,2,3])
>>> l[/color][/color][/color]
[3, 2, 1]
Michael | 
July 18th, 2005, 10:57 PM
| | | Re: Style guide for subclassing built-in types?
Michael Spencer wrote:[color=blue]
> janeaustine50@hotmail.com wrote:[color=green]
> > Kent Johnson wrote:
> >[color=darkred]
> >>janeaustine50@hotmail.com wrote:
> >>
> >>>p.s. the reason I'm not sticking to reversed or even reverse :[/color]
> >
> > suppose
> >[color=darkred]
> >>>the size of the list is huge.
> >>
> >>reversed() returns an iterator so list size shouldn't be an issue.
> >>
> >>What problem are you actually trying to solve?
> >>
> >>Kent
> >>[/color]
> >
> >
> > Oh, you are right.
> >
> > Actually, it's more complicated than simple reversion. The list[/color][/color]
order[color=blue][color=green]
> > should be somewhat "twisted" and the list is big.
> >
> > For example,
> >
> > [1,2,3,4,5,6,7,8,9,10]
> >
> > --> [10,9,8,7,6,1,2,3,4,5]
> >
> > so __getitem__(self,i) => __getitem__(self,-i-1) if i<len(size)/2,
> > otherwise __getitem__(self,i-len(size)/2)
> >
> > I'd like to have TwistedList class that takes in an original list[/color][/color]
and[color=blue][color=green]
> > pretends as if it is twisted actually. However, I have to have
> > duplicate codes here and there to make it act like a "list", say[/color][/color]
assert[color=blue][color=green]
> > twisted_list == [10,9,...] and for each in twisted_list and etc.
> >[/color]
> If you want a twisted 'view' of an existing list, then a wrapper[/color]
makes most sense.[color=blue]
>
> If, however, you only need the twisted version, why not simply[/color]
override[color=blue]
> list.__init__ (and extend, append etc... as required):
>[color=green][color=darkred]
> >>> class rev_list(list):[/color][/color]
> ... def __init__(self, iterable):
> ... list.__init__(self, iterable[::-1])
> ...[color=green][color=darkred]
> >>> l = rev_list([1,2,3])
> >>> l[/color][/color]
> [3, 2, 1]
>
> Michael[/color]
Thank you but your advice doesn't fit in my case since I want to keep
the memory usage and the initial time minimum. iterable[::-1] would
build another list and it would take big memory and time during
reversing if iterable were huge. (and the "iterable" wouldn't be
garbage-collected because I want to keep a reference to it) | 
July 18th, 2005, 10:58 PM
| | | Re: Style guide for subclassing built-in types?
In article <1109208924.563510.212500@f14g2000cwb.googlegroups .com>, janeaustine50@hotmail.com wrote:
[color=blue]
> Thank you but your advice doesn't fit in my case since I want to keep
> the memory usage and the initial time minimum. iterable[::-1] would
> build another list and it would take big memory and time during
> reversing if iterable were huge. (and the "iterable" wouldn't be
> garbage-collected because I want to keep a reference to it)[/color]
If your list contains numbers (or lists of numbers), consider using
NumPy (Numeric) or Numarray, in which seq[::-1] will actually return a
"view", and not a copy.
Just | 
July 18th, 2005, 10:58 PM
| | | Re: Style guide for subclassing built-in types? janeaustine50@hotmail.com wrote:[color=blue]
> Thank you but your advice doesn't fit in my case since I want to keep
> the memory usage and the initial time minimum. iterable[::-1] would
> build another list and it would take big memory and time during
> reversing if iterable were huge. (and the "iterable" wouldn't be
> garbage-collected because I want to keep a reference to it)[/color]
You need to implement __iter__ method to pass your assert statement:
def __iter__(self):
return reversed(self)
With regards to style guide:
1. write empty subclass
class rev_subclass(list):
pass
2. print dir(rev_subclass) and write unit tests for every method. There
are 41 of them :) There is also __doc__ attribute you need to override.
3. Implement all the methods of rev_subclass to pass the tests.
Serge. | 
July 18th, 2005, 10:58 PM
| | | Re: Style guide for subclassing built-in types? janeaustine50@hotmail.com wrote:[color=blue]
> Thank you but your advice doesn't fit in my case since I want to keep
> the memory usage and the initial time minimum. iterable[::-1] would
> build another list and it would take big memory and time during
> reversing if iterable were huge. (and the "iterable" wouldn't be
> garbage-collected because I want to keep a reference to it)[/color]
1. Do you have benchmark results or a mathematical analysis to show that
duplicating the list uses too much memory, or is too slow to startup?
2. Do you have quantitative definitions for "too much" and "too slow", and
rationale to back up those numbers?
3. Do you have a benchmark to determine if attempting to reduce memory
consumption and start-up time has a detrimental effect on run-time performance?
If the answer to any of the above questions is 'no', then just do something like:
from itertools import islice, chain
def twisted_iter(orig):
halfway, skip_middle = divmod(len(orig), 2)
fwditr = islice(iter(orig), halfway + skip_middle, None)
revitr = islice(reversed(orig), halfway, None)
return chain(revitr, fwditr)
Py> from itertools import islice, chain
Py> def twisted_iter(orig):
.... halfway, skip_middle = divmod(len(orig), 2)
.... fwditr = islice(iter(orig), halfway + skip_middle, None)
.... revitr = islice(reversed(orig), halfway, None)
.... return chain(revitr, fwditr)
....
Py> list(twisted_iter(range(10)))
[4, 3, 2, 1, 0, 5, 6, 7, 8, 9]
Py> list(twisted_iter(range(11)))
[5, 4, 3, 2, 1, 0, 6, 7, 8, 9, 10]
Since twisted_iter is actually a highly-optimised twisted view of the original
list, you may want to just leave the original list alone, and create
twisted_iter's when you want them.
However, if you mainly use the twisted view, and only occasionally want the
original view, then you can twist it once, store the result, discard the
original, and twist it again to get the original back:
Py> list(twistediter(list(twistediter(range(10)))))
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Py> list(twistediter(list(twistediter(range(11)))))
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Those benchmarks I mentioned earlier will let you know which approach is best.
No-optimisations-without-measurements-'ly,
Nick.
--
Nick Coghlan | ncoghlan@email.com | Brisbane, Australia
--------------------------------------------------------------- http://boredomandlaziness.skystorm.net |
Posting Rules
| You may not post new threads You may not post replies You may not post attachments You may not edit your posts HTML code is Off | | | | | | What is Bytes?
We are a network of experts and professionals in IT and software development that help one another with answers to tough questions and share insights.
Get the best answers to your questions from over network members.
|