Help | Site Map
Connecting Tech Pros Worldwide
 
 
LinkBack Thread Tools
  #1  
Old February 10th, 2006, 09:15 PM
Lonnie Princehouse
Guest
 
Posts: n/a
Default appending to a list via properties

Here's a curious hack I want to put up for discussion. I'm thinking of
writing a PEP for it.

Observation
-----------------
I found myself using this construct for assembling multiple lists:

foo = []
qux = []

while some_condition:
a, b = calculate_something()
foo.append(a)
qux.append(b)

Not elegant! It requires temporary variables a and b, which are only
used to populate the lists.


Suggestion
----------------

class better_list (list):
tail = property(None, list.append)

foo = better_list()
qux = better_list()

while some_condition:
foo.tail, qux.tail = calculate_something()

Granted, the name tail might not be the best, but you get the idea.


Alternatives
------------------

1. Use "append" instead, preserving original list.append behavior.

class better_list (list):
append = property(lambda l: lambda x: list.append(l,x),
list.append)

2. Use an external wrapper, similar to operator.*getter

class propertize (object):
def __init__(self, target):
self.__target__ = target
def __setattr__(self, attribute, value):
if attribute.startswith('_'): return
object.__setattr__(self, attribute, value)
else: getattr(self.__target__, attribute)(value)

propertize(foo).append, propertize(qux).append =
calculate_something()


Well?

  #2  
Old February 10th, 2006, 11:35 PM
Larry Bates
Guest
 
Posts: n/a
Default Re: appending to a list via properties

Lonnie Princehouse wrote:[color=blue]
> Here's a curious hack I want to put up for discussion. I'm thinking of
> writing a PEP for it.
>
> Observation
> -----------------
> I found myself using this construct for assembling multiple lists:
>
> foo = []
> qux = []
>
> while some_condition:
> a, b = calculate_something()
> foo.append(a)
> qux.append(b)
>
> Not elegant! It requires temporary variables a and b, which are only
> used to populate the lists.
>
>
> Suggestion
> ----------------
>
> class better_list (list):
> tail = property(None, list.append)
>
> foo = better_list()
> qux = better_list()
>
> while some_condition:
> foo.tail, qux.tail = calculate_something()
>
> Granted, the name tail might not be the best, but you get the idea.
>
>
> Alternatives
> ------------------
>
> 1. Use "append" instead, preserving original list.append behavior.
>
> class better_list (list):
> append = property(lambda l: lambda x: list.append(l,x),
> list.append)
>
> 2. Use an external wrapper, similar to operator.*getter
>
> class propertize (object):
> def __init__(self, target):
> self.__target__ = target
> def __setattr__(self, attribute, value):
> if attribute.startswith('_'): return
> object.__setattr__(self, attribute, value)
> else: getattr(self.__target__, attribute)(value)
>
> propertize(foo).append, propertize(qux).append =
> calculate_something()
>
>
> Well?
>[/color]
Not entirely sure I understand, but here goes. I normally
use list comprehensions. I'm assuming that calculate_something()
is acting on a list of items. If not then maybe some underlying
data refactoring is in order. If so you write:

results=[calculate_something(x) for x in list_of_items]
foo=result[x[0] for x in results]
qux=result[x[1] for x in results]

Without knowing more about what calculate_something() does
and what condition terminates the loop it is hard to say if
this will work for you.

-Larry Bates
  #3  
Old February 11th, 2006, 03:25 PM
Carl Banks
Guest
 
Posts: n/a
Default Re: appending to a list via properties

Lonnie Princehouse wrote:[color=blue]
> Here's a curious hack I want to put up for discussion. I'm thinking of
> writing a PEP for it.[/color]

A minor library change wouldn' t need a PEP.
[color=blue]
> Observation
> -----------------
> I found myself using this construct for assembling multiple lists:
>
> foo = []
> qux = []
>
> while some_condition:
> a, b = calculate_something()
> foo.append(a)
> qux.append(b)
>
> Not elegant![/color]

I don't agree; however:
[color=blue]
> class better_list (list):
> tail = property(None, list.append)[/color]

This is an impressive, spiffy little class.
[color=blue]
> Well?[/color]

I suspect it's too sneaky and not commonly useful enough to get serious
consideration for the standard library. But definitely submit it to
Python Cookbook:
http://aspn.activestate.com/ASPN/Python/Cookbook/

Carl Banks


P.S. to get rid of temporary variables while using regular lists:

growing_lists = foo,qux
while some_condition:
for (s,x) in zip(growing_list,calculate_something()):
list.append(s,x)

No I don't really recommend it.

  #4  
Old February 11th, 2006, 05:15 PM
Alex Martelli
Guest
 
Posts: n/a
Default Re: appending to a list via properties

Carl Banks <invalidemail@aerojockey.com> wrote:
...[color=blue][color=green]
> > class better_list (list):
> > tail = property(None, list.append)[/color]
>
> This is an impressive, spiffy little class.[/color]

Yes, nice use of property.
[color=blue]
> growing_lists = foo,qux
> while some_condition:
> for (s,x) in zip(growing_list,calculate_something()):
> list.append(s,x)
>
> No I don't really recommend it.[/color]

Why not? Seems OK. Maybe simplified to:

while some_condition:
for alist, anitem in zip((foo, qux), calculate_something()):
alist.append(anitem)

If you want to hoist for performance, you can hoist more:

appenders = foo.append, qux.append
while some_condition:
for appender, anitem in zip(appenders, calculate_something()):
appender(anitem)


Alex
  #5  
Old February 11th, 2006, 05:35 PM
Carl Banks
Guest
 
Posts: n/a
Default Re: appending to a list via properties


Alex Martelli wrote:[color=blue]
> Carl Banks <invalidemail@aerojockey.com> wrote:
> ...[color=green][color=darkred]
> > > class better_list (list):
> > > tail = property(None, list.append)[/color]
> >
> > This is an impressive, spiffy little class.[/color]
>
> Yes, nice use of property.
>[color=green]
> > growing_lists = foo,qux
> > while some_condition:
> > for (s,x) in zip(growing_list,calculate_something()):
> > list.append(s,x)
> >
> > No I don't really recommend it.[/color]
>
> Why not? Seems OK. Maybe simplified to:[/color]

Well, for this simple case I guess. If you have a lot of lists, or
you're trying to write a general multiple list appender, it would be
fine.

Carl Banks

  #6  
Old February 12th, 2006, 12:15 AM
Xavier Morel
Guest
 
Posts: n/a
Default Re: appending to a list via properties

Alex Martelli wrote:[color=blue]
> Carl Banks <invalidemail@aerojockey.com> wrote:
> ...[color=green][color=darkred]
>>> class better_list (list):
>>> tail = property(None, list.append)[/color]
>> This is an impressive, spiffy little class.[/color]
>
> Yes, nice use of property.
>
> Alex[/color]

I don't know, I usually see people considering that properties are
"cool" as long as they don't have side effects, as long as they're
virtual members.

The tail property doesn't behave like member data at all, the semantics
are strange, counter-intuitive (tail would usually be the end of the
list, either [-1] or [1:], in this case it's some magic position at the
end of the list). And it has one hell of a side effect.
  #7  
Old February 12th, 2006, 02:05 AM
Alex Martelli
Guest
 
Posts: n/a
Default Re: appending to a list via properties

Xavier Morel <xavier.morel@masklinn.net> wrote:
[color=blue]
> Alex Martelli wrote:[color=green]
> > Carl Banks <invalidemail@aerojockey.com> wrote:
> > ...[color=darkred]
> >>> class better_list (list):
> >>> tail = property(None, list.append)
> >> This is an impressive, spiffy little class.[/color]
> >
> > Yes, nice use of property.
> >
> > Alex[/color]
>
> I don't know, I usually see people considering that properties are
> "cool" as long as they don't have side effects, as long as they're
> virtual members.[/color]

If a property didn't have any side effects, there would be no reason to
define it as a property. I do fully expect x.y=z to have "side effects"
on z when y is an assignable property.
[color=blue]
> The tail property doesn't behave like member data at all, the semantics
> are strange, counter-intuitive (tail would usually be the end of the
> list, either [-1] or [1:], in this case it's some magic position at the
> end of the list). And it has one hell of a side effect.[/color]

The name 'tail' may not be ideal (for people coming from languages where
'head' is the first element and 'tail' is all the others, in
particular). But the side effect doesn't look hellish at all to me.


Alex
  #8  
Old February 12th, 2006, 04:15 PM
Peter Otten
Guest
 
Posts: n/a
Default Re: appending to a list via properties

[Alex Martelli]
[color=blue]
> If you want to hoist for performance, you can hoist more:
>
> appenders = foo.append, qux.append
> while some_condition:
> for appender, anitem in zip(appenders, calculate_something()):
> appender(anitem)[/color]

You are of course claiming a performance improvement over Carl's variant,
but looking back into the initial post

[Lonnie Princehouse]
[color=blue]
> foo = []
> qux = []
>
> while some_condition:
> a, b = calculate_something()
> foo.append(a)
> qux.append(b)[/color]

the original code looks like yours with the inner loop unrolled - a classic
measure for performance improvement.

$ python -m timeit -s'ext = [].extend, [].extend' -s'def calc(): return (),
()' 'for ix, i in zip(ext, calc()): ix(i)'
100000 loops, best of 3: 2.79 usec per loop

$ python -m timeit -s'ax = [].extend; bx = [].extend' -s'def calc(): return
(), ()' 'a, b = calc(); ax(a); bx(b)'
1000000 loops, best of 3: 0.975 usec per loop

(I used extend instead of append() to avoid the effects of memory hogging)

I find the faster code more readable than yours - and Lonnie's cool hack -
so I'd leave it at that.

Peter

 

Bookmarks

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 Off
[IMG] code is Off
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are On

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.
Post your question now . . .
It's fast and it's free

Popular Articles