Multi-dimensional list initialization

Andrew Robinson andrew3 at r3dsolutions.com
Wed Nov 7 22:13:25 EST 2012


On 11/07/2012 03:39 PM, Ian Kelly wrote:
> Why? Just to get rid of an FAQ? 
:-)

> Here's one of the more interesting uses from my own code:
OK, and is this a main use case?  (I'm not saying it isn't I'm asking.)

> Replacing the list multiplication in that function with a list 
> comprehension would be awkward, as the obvious replacement of 
> [iter(iterable) for _ in range(n)] would produce different results.

Yes. I have a thought on that.
> How exactly do you propose to indicate to the compiler which parts of 
> the expressions are meant to be cached, and which are not?

Exactly?
OK; Here's what I would consider a safe implementation -- but it could 
be improved later.
There is a special keyword which signals the new type of comprehension;  
A normal comprehension would say eg: '[ foo for i in xrange ]'; but when 
the 'for i in' is reduced to a specific keyword such as 'ini' (instead 
of problematic 'in') the caching form of list comprehension would start.

So, then, just like a comprehension -- the interpreter will begin to 
evaluate the code from the opening bracket '['; But anything other than 
a function/method will raise a type error (people might want to change 
that, but it's safe).

The interpreter then caches all functions/initialiser methods it comes 
into contact with.
Since every function/method has a parameter list (even if empty);  The 
interpreter would evaluate the parameter list on the first pass through 
the comprehension, and cache each parameter list with it's respective 
function.

When the 'ini' keyword is parsed a second time, Python would then 
evaluate each cached function on its cached parameter list; and the 
result would be stored in the created list.
This cached execution would be repeated as many times as is needed.

Now, for your example:
> values = zip(samples, times * num_groups)
>      if len(values)<  len(times) * num_groups:
>          # raise an error
Might be done with:

values = zip(   samples, [ lambda:times, ini xrange(num_groups) ]   )
     if len(values) < len(times) * num_groups

The comma after the lambda is questionable, and this construction would 
be slower since lambda automatically invokes the interpreter; but it's 
correct.

If you could provide a built in which returns a reference to the 
parameter passed to it; that would run at max system speed; by default, 
all built-in object initializers are maximally fast.

The key difference is that the ini syntax evaluates the parameter lists 
only once; and the ini's purpose is for repeating an initialization of 
the same kind of object in multiple different places.

As an aside, how would you do the lambda inside a list comprehension?
[lambda:6 for i in xrange(10) ] # Nope.
Generic lists allow a spurrious comma, so that [  3,3,3, ] = [3,3,3] 
dropped;
[lambda:6, for i in xrange(10) ] # but this is no good.

I have to do:
def ref(): return 6
[ref(x) for i in xrange(10) ]

> Of course you got an integer. You took an index of the range object, 
> not a slice. The rule is that taking an index of a sequence returns an 
> element; taking a slice of a sequence returns a sub-sequence. You 
> still have not shown any inconsistency here.

Because it's an arbitrary rule which operates differently than the 
traditional idea shown in python docs?

slice.indices()  is *for* (QUOTE)"representing the _set of indices_ 
specified by _range_(start, stop, step)"
http://docs.python.org/2/library/functions.html#slice

There are examples of python doing this; use Google...  They use slice 
indices() to convert negative indexes into positive ones _compatible 
with range()_.

some_getitem_method_in_a_subclass_foo( self, range ):
     ret=[]
     for i in xrange( range.indices( len(self) ) ):
         ret.append( self.thing[i] )
     return ret

The return is equivalent to a range object in the sense that it is an 
iterator object, but it's not the same iterator object.  It will still 
work with legacy code.... since different iterators can be interchanged 
so long as they return the same values.

> No, he wasn't. He was talking about multiplying lists of dicts, and 
> whether the dicts are then copied or not, just like every other Q&A 
> item in that dialogue was concerning whether item X in a list should 
> expect to be copied when the containing list is multiplied.

I already told him several times before that what the answer was;
It doesn't copy anything except the list itself.

Then he asks, "does it multiply dicts" and no mention of it being inside 
a list.
He's browbeating a dead horse.

> Perhaps you're not aware that on the Internet, TYPING IN ALL CAPS is 
> commonly construed as SHOUTING. 
Sure, and people say:

THIS IS YELLING, AND I AM DOING IT HERE AS AN EXAMPLE.
This is STRESS.
This is SHOCK!

I don't recall typing any _full sentence_ in all caps, if I did, I'm 
awfully sorry.  I didn't mean it.
Yes, he is beginning to get condescendingly exasperating.  Everyone else 
seems to understand 85+% of what I say, correctly.  He doesn't; and now 
replying to him appears to confuse everyone else.


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-list/attachments/20121107/126083a8/attachment.html>


More information about the Python-list mailing list