Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.python > #32748 > unrolled thread

Multi-dimensional list initialization

Started byDemian Brecht <demianbrecht@gmail.com>
First post2012-11-04 22:27 -0800
Last post2012-11-05 01:55 -0800
Articles 19 on this page of 59 — 20 participants

Back to article view | Back to comp.lang.python


Contents

  Multi-dimensional list initialization Demian Brecht <demianbrecht@gmail.com> - 2012-11-04 22:27 -0800
    Re: Multi-dimensional list initialization Hans Mulder <hansmu@xs4all.nl> - 2012-11-05 10:13 +0100
      Re: Multi-dimensional list initialization Oscar Benjamin <oscar.j.benjamin@gmail.com> - 2012-11-06 01:32 +0000
      Re: Multi-dimensional list initialization Chris Angelico <rosuav@gmail.com> - 2012-11-06 13:01 +1100
      Re: Multi-dimensional list initialization Oscar Benjamin <oscar.j.benjamin@gmail.com> - 2012-11-06 02:30 +0000
      Re: Multi-dimensional list initialization Andrew Robinson <andrew3@r3dsolutions.com> - 2012-11-05 21:51 -0800
        Re: Multi-dimensional list initialization Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2012-11-06 09:04 +0000
          RE: Multi-dimensional list initialization "Shambhu Rajak" <shambhu.rajak@calsoftinc.com> - 2012-11-06 18:57 +0530
          Re: Multi-dimensional list initialization Andrew Robinson <andrew3@r3dsolutions.com> - 2012-11-06 14:41 -0800
            Re: Multi-dimensional list initialization Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2012-11-07 01:55 +0000
              Re: Multi-dimensional list initialization Demian Brecht <demianbrecht@gmail.com> - 2012-11-06 22:56 -0800
              Re: Multi-dimensional list initialization wxjmfauth@gmail.com - 2012-11-07 00:57 -0800
              Re: Multi-dimensional list initialization Mark Lawrence <breamoreboy@yahoo.co.uk> - 2012-11-07 22:27 +0000
              Re: Multi-dimensional list initialization Ian Kelly <ian.g.kelly@gmail.com> - 2012-11-07 16:39 -0700
              Re: Multi-dimensional list initialization Ian Kelly <ian.g.kelly@gmail.com> - 2012-11-08 00:09 -0700
              Re: Multi-dimensional list initialization Ian Kelly <ian.g.kelly@gmail.com> - 2012-11-08 08:58 -0700
              Re: Multi-dimensional list initialization Mark Lawrence <breamoreboy@yahoo.co.uk> - 2012-11-09 01:39 +0000
              Re: Multi-dimensional list initialization Chris Angelico <rosuav@gmail.com> - 2012-11-09 17:07 +1100
                Re: Multi-dimensional list initialization Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2012-11-09 06:37 +0000
                  Re: Multi-dimensional list initialization Chris Angelico <rosuav@gmail.com> - 2012-11-09 17:59 +1100
                  Re: Multi-dimensional list initialization Mark Lawrence <breamoreboy@yahoo.co.uk> - 2012-11-09 07:27 +0000
                  Re: Multi-dimensional list initialization rusi <rustompmody@gmail.com> - 2012-11-09 07:05 -0800
                    Re: Multi-dimensional list initialization Chris Angelico <rosuav@gmail.com> - 2012-11-10 02:23 +1100
              Re: Multi-dimensional list initialization Dennis Lee Bieber <wlfraed@ix.netcom.com> - 2012-11-09 14:34 -0500
              RE: Multi-dimensional list initialization "Prasad, Ramit" <ramit.prasad@jpmorgan.com> - 2012-11-09 20:31 +0000
              Re: Multi-dimensional list initialization Ethan Furman <ethan@stoneleaf.us> - 2012-11-09 13:49 -0800
          RE: Multi-dimensional list initialization "Prasad, Ramit" <ramit.prasad@jpmorgan.com> - 2012-11-06 23:39 +0000
          Re: Multi-dimensional list initialization Ian Kelly <ian.g.kelly@gmail.com> - 2012-11-06 16:52 -0700
          Re: Multi-dimensional list initialization MRAB <python@mrabarnett.plus.com> - 2012-11-07 00:23 +0000
            Re: Multi-dimensional list initialization rusi <rustompmody@gmail.com> - 2012-11-06 20:11 -0800
            Re: Multi-dimensional list initialization Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2012-11-07 05:05 +0000
              Re: Multi-dimensional list initialization Roy Smith <roy@panix.com> - 2012-11-07 00:12 -0500
                Re: Multi-dimensional list initialization Gregory Ewing <greg.ewing@canterbury.ac.nz> - 2012-11-07 18:32 +1300
                  RE: Multi-dimensional list initialization "Prasad, Ramit" <ramit.prasad@jpmorgan.com> - 2012-11-07 15:57 +0000
              Re: Multi-dimensional list initialization Jussi Piitulainen <jpiitula@ling.helsinki.fi> - 2012-11-07 10:52 +0200
              Re: Multi-dimensional list initialization MRAB <python@mrabarnett.plus.com> - 2012-11-07 17:17 +0000
                Re: Multi-dimensional list initialization Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2012-11-07 22:36 +0000
          Re: Multi-dimensional list initialization Ethan Furman <ethan@stoneleaf.us> - 2012-11-07 07:23 -0800
          Re: Multi-dimensional list initialization Ian Kelly <ian.g.kelly@gmail.com> - 2012-11-07 14:01 -0700
            Re: Multi-dimensional list initialization Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2012-11-08 00:00 +0000
              Re: Multi-dimensional list initialization Oscar Benjamin <oscar.j.benjamin@gmail.com> - 2012-11-08 00:30 +0000
                Re: Multi-dimensional list initialization Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2012-11-08 03:47 +0000
              Re: Multi-dimensional list initialization Andrew Robinson <andrew3@r3dsolutions.com> - 2012-11-07 20:51 -0800
              Re: Multi-dimensional list initialization wrw@mac.com - 2012-11-08 08:26 -0500
          Re: Multi-dimensional list initialization Andrew Robinson <andrew3@r3dsolutions.com> - 2012-11-07 16:24 -0800
            Re: Multi-dimensional list initialization Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2012-11-08 04:20 +0000
      Re: Multi-dimensional list initialization Chris Angelico <rosuav@gmail.com> - 2012-11-06 17:07 +1100
      Re: Multi-dimensional list initialization Andrew Robinson <andrew3@r3dsolutions.com> - 2012-11-06 00:21 -0800
      Re: Multi-dimensional list initialization Ian Kelly <ian.g.kelly@gmail.com> - 2012-11-06 02:19 -0700
      RE: Multi-dimensional list initialization "Prasad, Ramit" <ramit.prasad@jpmorgan.com> - 2012-11-06 17:32 +0000
      Re: Multi-dimensional list initialization Andrew Robinson <andrew3@r3dsolutions.com> - 2012-11-06 13:14 -0800
      Re: Multi-dimensional list initialization Andrew Robinson <andrew3@r3dsolutions.com> - 2012-11-06 13:19 -0800
      Re: Multi-dimensional list initialization Ian Kelly <ian.g.kelly@gmail.com> - 2012-11-06 15:46 -0700
        Re: Multi-dimensional list initialization Gregory Ewing <greg.ewing@canterbury.ac.nz> - 2012-11-07 18:34 +1300
          Re: Multi-dimensional list initialization Oscar Benjamin <oscar.j.benjamin@gmail.com> - 2012-11-07 14:00 +0000
          Re: Multi-dimensional list initialization Ethan Furman <ethan@stoneleaf.us> - 2012-11-07 06:47 -0800
          Re: Multi-dimensional list initialization Oscar Benjamin <oscar.j.benjamin@gmail.com> - 2012-11-07 23:06 +0000
          Re: Multi-dimensional list initialization Greg Ewing <greg.ewing@canterbury.ac.nz> - 2012-11-08 14:29 +1300
    Re: Multi-dimensional list initialization wxjmfauth@gmail.com - 2012-11-05 01:55 -0800

Page 3 of 3 — ← Prev page 1 2 [3]


#32926

FromOscar Benjamin <oscar.j.benjamin@gmail.com>
Date2012-11-08 00:30 +0000
Message-ID<mailman.3414.1352334655.27098.python-list@python.org>
In reply to#32923
On 8 November 2012 00:00, Steven D'Aprano
<steve+comp.lang.python@pearwood.info> wrote:
> Andrew, it appears that your posts are being eaten or rejected by my
> ISP's news server, because they aren't showing up for me. Possibly a side-
> effect of your dates being in the distant past? So if you have replied to
> any of my posts, I haven't seen them.
>
> In any case, I wanted to ask a question:
>
>
> On Wed, 07 Nov 2012 14:01:19 -0700, Ian Kelly wrote:
>> On Wed, Nov 7, 2012 at 12:51 PM, Andrew Robinson
>> <andrew3@r3dsolutions.com> wrote:
>
> [...]
>
>>> But, in any event:
>>> Pass by value (not call by value) is a term stretching back 30 years;
>>> eg: when I learned the meaning of the words.  Rewording it as "Call by
>>> value" is something that happened later, and the nuance is lost on
>>> those without a very wide programming knowledge *and* age.
>
> Every now and again I come across somebody who tries to distinguish
> between "call by foo" and "pass by foo", but nobody has been able to
> explain the difference (if any) to me. When you CALL a function, you PASS
> values to it. Hence the two terms are effectively synonyms, and both
> refer to the evaluation strategy when binding arguments to parameters.
>
> If you believe that is incorrect, can you point me to something
> explaining the difference?

Did you also miss MRAB's post above? It made sense to me.

MRAB wrote:
> The disadvantage of calling it "call by ..." is that it suggests that
> you're just talking about calling functions.
>
> What about binding in general, eg "x = y"? Does it make sense to still
> call it "call by ..."?

[toc] | [prev] | [next] | [standalone]


#32929

FromSteven D'Aprano <steve+comp.lang.python@pearwood.info>
Date2012-11-08 03:47 +0000
Message-ID<509b2b5c$0$29885$c3e8da3$5496439d@news.astraweb.com>
In reply to#32926
On Thu, 08 Nov 2012 00:30:53 +0000, Oscar Benjamin wrote:

>> Every now and again I come across somebody who tries to distinguish
>> between "call by foo" and "pass by foo", but nobody has been able to
>> explain the difference (if any) to me. When you CALL a function, you
>> PASS values to it. Hence the two terms are effectively synonyms, and
>> both refer to the evaluation strategy when binding arguments to
>> parameters.
>>
>> If you believe that is incorrect, can you point me to something
>> explaining the difference?
> 
> Did you also miss MRAB's post above? It made sense to me.

You mean MRABs post which I replied to?

Yes, I must have missed it :-P

But seriously, no I didn't miss it. He doesn't give any evidence that 
there is a difference between "call by ..." and "pass by ..." when 
talking about binding arguments to formal parameters. His objection to 
"call by ..." is that it doesn't make it clear that the evaluation rules 
apply to simple binding/assignment as well as calling functions.



-- 
Steven

[toc] | [prev] | [next] | [standalone]


#32931

FromAndrew Robinson <andrew3@r3dsolutions.com>
Date2012-11-07 20:51 -0800
Message-ID<mailman.3419.1352350234.27098.python-list@python.org>
In reply to#32923
On 11/07/2012 04:00 PM, Steven D'Aprano wrote:
> Andrew, it appears that your posts are being eaten or rejected by my
> ISP's news server, because they aren't showing up for me. Possibly a side-
> effect of your dates being in the distant past?
Date has been corrected since two days ago.  It will remain until a 
reboot....
Ignorance, though, might be bliss...

> Every now and again I come across somebody who tries to distinguish 
> between "call by foo" and "pass by foo", but nobody has been able to 
> explain the difference (if any) to me.
I think the "Call by foo" came into vogue around the time of C++; Eg: 
It's in books like C++ for C programmers;  I never saw it used before 
then so I *really* don't know for sure...

I know "Pass by value" existed all the way back to the 1960's.  I see 
"pass by" in my professional books from those times and even most newer 
ones; but I only find "Call by value" in popular programming books of 
more recent times.  (Just my experience)  So -- I "guess" the reason is 
that when invoking a subroutine, early hardware often had an assembler 
mnemonic by the name "call".

See for example: Intelx86 hardware books from the 1970's;

Most early processors (like the MC6809E, and 8080) allow both direct and 
indirect *references* to a function (C would call them function 
pointers); So, occasionally early assembly programs comment things like: 
"; dynamic VESA libraries are called by value in register D.";  And they 
meant that register D is storing a function call address from two or 
more vesa cards.  It had little to do with the function's parameters, 
(which might be globals anyway)  (It procedural dynamic binding!)

Today, I don't know for sure -- so I just don't use it.
"pass" indicates a parameter of the present call; but not the present 
call itself.

[toc] | [prev] | [next] | [standalone]


#32953

Fromwrw@mac.com
Date2012-11-08 08:26 -0500
Message-ID<mailman.3438.1352384823.27098.python-list@python.org>
In reply to#32923
On Nov 7, 2012, at 11:51 PM, Andrew Robinson <andrew3@r3dsolutions.com> wrote:

> On 11/07/2012 04:00 PM, Steven D'Aprano wrote:
>> Andrew, it appears that your posts are being eaten or rejected by my
>> ISP's news server, because they aren't showing up for me. Possibly a side-
>> effect of your dates being in the distant past?
> Date has been corrected since two days ago.  It will remain until a reboot....
> Ignorance, though, might be bliss...
> 
>> Every now and again I come across somebody who tries to distinguish between "call by foo" and "pass by foo", but nobody has been able to explain the difference (if any) to me.
> I think the "Call by foo" came into vogue around the time of C++; Eg: It's in books like C++ for C programmers;  I never saw it used before then so I *really* don't know for sure…
> 

Just as an aside - there is a famous quote from Niklaus Wirt, who, when asked how he pronounced his name, is said to have replied:  "Well you can call me by name, Veert, or you can call me by value, Worth."

That would have been sometime in the early 60s, when he was at Stanford.

-Bill

[toc] | [prev] | [next] | [standalone]


#32925

FromAndrew Robinson <andrew3@r3dsolutions.com>
Date2012-11-07 16:24 -0800
Message-ID<mailman.3413.1352334232.27098.python-list@python.org>
In reply to#32811
On 11/07/2012 01:01 PM, Ian Kelly wrote:
> On Wed, Nov 7, 2012 at 12:51 PM, Andrew Robinson
> <andrew3@r3dsolutions.com>  wrote:
>> Interesting, you avoided the main point "lists are copied with list
>> multiplication".
> It seems that each post is longer than the last.  If we each responded
> to every point made, this thread would fill a book.
It already is :)
>
> Anyway, your point was to suggest that people would not be confused by
> having list multiplication copy lists but not other objects, because
> passing lists into functions as parameters works in basically the same
> way.
Not quite; Although I wasn't clear;  The variable passed in is by 
*value* in contradistinction to the list which is by reference.  Python 
does NOT always default copy by reference *when it could*; that's the point.

Hence the programmer has to remember in  foo( x,y ), the names x and y 
when assigned to -- *DONT* affect the variables from which they came.  
But any object internals do affect the objects everywhere.

A single exception exists; My thesis is for a single exception as well 
-- I think Python allows that kind of thinking.
> So actually I did address
> this point with the "call-by-object" tangent; I just did not
> explicitly link it back to your thesis.
My apology for not proof reading my statements for clarity.  It was 
definitely time for a nap back then.

> Potayto, potahto. The distinction that you're describing is between 
> "strict" versus "non-strict" evaluation strategies. Hinging the 
> distinction on the non-descriptive words "call" and "pass" is lazy 
> terminology that should never have been introduced in the first place.
I would do it again.  Other's have already begun to discuss terminology 
with you -- I won't double team you.


[toc] | [prev] | [next] | [standalone]


#32930

FromSteven D'Aprano <steve+comp.lang.python@pearwood.info>
Date2012-11-08 04:20 +0000
Message-ID<509b3308$0$29885$c3e8da3$5496439d@news.astraweb.com>
In reply to#32925
On Wed, 07 Nov 2012 16:24:22 -0800, Andrew Robinson wrote:

> On 11/07/2012 01:01 PM, Ian Kelly wrote:
[...]
>> Anyway, your point was to suggest that people would not be confused by
>> having list multiplication copy lists but not other objects, because
>> passing lists into functions as parameters works in basically the same
>> way.
>
> Not quite; Although I wasn't clear;  The variable passed in is by
> *value* in contradistinction to the list which is by reference.  Python
> does NOT always default copy by reference *when it could*; that's the
> point.

It isn't clear to me whether you are describing what you think Python 
*actually* does, versus what you wish it *would* do, or what it *could* 
do in some abstract hypothetical sense.

It certainly is not true that Python passes "the variable" by value, and 
lists "by reference". Arguments are not passed to functions either by 
value or by reference.

There is a trivial test for pass-by-value semantics: does the value get 
copied? We can see that Python does not copy arguments:

py> def test(x):
...     print id(x)
... 
py> spam = []
py> print id(spam); test(spam)
3071264556
3071264556

The argument is not copied, therefore Python is not pass-by-value.

There is also an easy test for pass-by-reference semantics: can you write 
a procedure which, given two variables, swaps the contents of the 
variables? In Pascal, that is trivial.

procedure swap(var a: int, var b: int):
  var
    tmp: int;
  begin
    tmp := a;
    a := b;
    b := a;
  end;

swap(x, y);

(if I've remembered my Pascal syntax correctly).


In Python, you can swap two values like this:

a, b = b, a

but that's not sufficient. The test is to do the swap inside a function:

def swap(a, b):
    return b, a

b, a = swap(a, b)

But that fails too, since the assignment is still taking place outside 
the function.

It turns out that there is no way in Python to write such a swap 
function. Tricks such as passing the variable names as strings, then 
using exec, are hacks and don't count. Python is not pass by reference 
either.



> Hence the programmer has to remember in  foo( x,y ), the names x and y
> when assigned to -- *DONT* affect the variables from which they came.
> But any object internals do affect the objects everywhere.

Ummm.... yes?

The programmer has to remember Python's execution model in order to 
correctly predict what Python will do. What's your point?


> A single exception exists; 

There is no such exception in Python. Python always uses the same 
argument passing (parameter binding) semantics.



-- 
Steven

[toc] | [prev] | [next] | [standalone]


#32807

FromChris Angelico <rosuav@gmail.com>
Date2012-11-06 17:07 +1100
Message-ID<mailman.3312.1352182028.27098.python-list@python.org>
In reply to#32762
On Tue, Nov 6, 2012 at 4:51 PM, Andrew Robinson
<andrew3@r3dsolutions.com> wrote:
> I really don't think doing a shallow copy of lists would break anyone's
> program.

Well, it's a change, a semantic change. It's almost certainly going to
break _something_. But for the sake of argument, we can suppose that
the change could be made. Would it be the right thing to do?

Shallow copying by default would result in extremely weird behaviour.
All the same confusion would result, only instead of comparing
[None]*4 with [[None]]*4, there'd be confusion over the difference
between [[None]]*4 and [[[None]]]*4.

I don't think it would help anything, and it'd result in a lot more
work for no benefit.

ChrisA

[toc] | [prev] | [next] | [standalone]


#32808

FromAndrew Robinson <andrew3@r3dsolutions.com>
Date2012-11-06 00:21 -0800
Message-ID<mailman.3313.1352190429.27098.python-list@python.org>
In reply to#32762
On 11/05/2012 10:07 PM, Chris Angelico wrote:
> On Tue, Nov 6, 2012 at 4:51 PM, Andrew Robinson
> <andrew3@r3dsolutions.com>  wrote:
>> I really don't think doing a shallow copy of lists would break anyone's
>> program.
> Well, it's a change, a semantic change. It's almost certainly going to
> break _something_. But for the sake of argument, we can suppose that
> the change could be made. Would it be the right thing to do?
>
> Shallow copying by default would result in extremely weird behaviour.
> All the same confusion would result, only instead of comparing
> [None]*4 with [[None]]*4, there'd be confusion over the difference
> between [[None]]*4 and [[[None]]]*4.
>
> I don't think it would help anything, and it'd result in a lot more
> work for no benefit.
>
> ChrisA
I don't follow.
a=[ None ]*4 would give a=[ None, None, None, None ] as usual.
All four None's would be the same object, but there are automatically 4 
different pointers to it.
Hence,
a[0]=1 would give a=[ 1, None, None, None ] as usual.

a=[ [None] ]*4 would give a=[ [None], [None], [None], [None] ] as usual
BUT:
a[0][0] = 1 would no longer give a=[ [1],[1],[1],[1] ] *Rather* it would 
give
a=[ [1].[None].[None],[None] ]

The None objects are all still the same one, BUT the lists themselves 
are different.

Again, a=[ ["alpha","beta"] * 4 ] would give:
a=[ ["alpha","beta"], ["alpha","beta"], ["alpha","beta"], ["alpha","beta"] ]

All four strings, "alpha", are the same object -- but there are 5 
different lists;  The pointers inside the initial list are copied four 
times -- not the string objects;
But the *lists* themselves are created new for each replication.

If you nest it another time;
[[[None]]]*4, the same would happen; all lists would be independent -- 
but the objects which aren't lists would be refrenced-- not copied.

a=[[["alpha","beta"]]]*4 would yield:
a=[[['alpha', 'beta']], [['alpha', 'beta']], [['alpha', 'beta']], 
[['alpha', 'beta']]]
and a[0][0]=1 would give [[1],[['alpha', 'beta']], [['alpha', 'beta']], 
[['alpha', 'beta']]]]
rather than a=[[1], [1], [1], [1]]

Or at another level down: a[0][0][0]=1 would give: a=[[[1, 'beta']], 
[['alpha', 'beta']], [['alpha', 'beta']], [['alpha', 'beta']] ]
rather than a=[[[1, 'beta']], [[1, 'beta']], [[1, 'beta']], [[1, 'beta']]]

The point is, there would be no difference at all noticed in what data 
is found where in the array;
the *only* thing that would change is that replacing an item by 
assignment would only affect the *location* assigned to -- all other 
locations would not be affected.

That really is what people *generally* want.
If the entire list is meant to be read only -- the change would affect 
*nothing* at all.

See if you can find *any* python program where people desired the 
multiplication to have the die effect that changing an object in one of 
the sub lists -- changes all the objects in the other sub lists.

I'm sure you're not going to find it -- and even if you do, it's going 
to be 1 program in 1000's.

[toc] | [prev] | [next] | [standalone]


#32812

FromIan Kelly <ian.g.kelly@gmail.com>
Date2012-11-06 02:19 -0700
Message-ID<mailman.3316.1352193584.27098.python-list@python.org>
In reply to#32762
On Tue, Nov 6, 2012 at 1:21 AM, Andrew Robinson
<andrew3@r3dsolutions.com> wrote:
> If you nest it another time;
> [[[None]]]*4, the same would happen; all lists would be independent -- but
> the objects which aren't lists would be refrenced-- not copied.
>
> a=[[["alpha","beta"]]]*4 would yield:
> a=[[['alpha', 'beta']], [['alpha', 'beta']], [['alpha', 'beta']], [['alpha',
> 'beta']]]
> and a[0][0]=1 would give [[1],[['alpha', 'beta']], [['alpha', 'beta']],
> [['alpha', 'beta']]]]
> rather than a=[[1], [1], [1], [1]]
>
> Or at another level down: a[0][0][0]=1 would give: a=[[[1, 'beta']],
> [['alpha', 'beta']], [['alpha', 'beta']], [['alpha', 'beta']] ]
> rather than a=[[[1, 'beta']], [[1, 'beta']], [[1, 'beta']], [[1, 'beta']]]

You wrote "shallow copy".  When the outer-level list is multiplied,
the mid-level lists would be copied.  Because the copies are shallow,
although the mid-level lists are copied, their contents are not.  Thus
the inner-level lists would still be all referencing the same list.
To demonstrate:

>>> from copy import copy
>>> class ShallowCopyList(list):
...     def __mul__(self, number):
...         new_list = ShallowCopyList()
...         for _ in range(number):
...             new_list.extend(map(copy, self))
...         return new_list
...
>>> a = ShallowCopyList([[["alpha", "beta"]]])
>>> a
[[['alpha', 'beta']]]
>>> b = a * 4
>>> b
[[['alpha', 'beta']], [['alpha', 'beta']], [['alpha', 'beta']],
[['alpha', 'beta']]]
>>> b[0][0][0] = 1
>>> b
[[[1, 'beta']], [[1, 'beta']], [[1, 'beta']], [[1, 'beta']]]
>>> b[0][0] = 1
>>> b
[[1], [[1, 'beta']], [[1, 'beta']], [[1, 'beta']]]

This shows that assignments at the middle level are independent with a
shallow copy on multiplication, but assignments at the inner level are
not.  In order to achieve the behavior you describe, a deep copy would
be needed.

> That really is what people *generally* want.
> If the entire list is meant to be read only -- the change would affect
> *nothing* at all.

The time and memory cost of the multiplication operation would become
quadratic instead of linear.

> See if you can find *any* python program where people desired the
> multiplication to have the die effect that changing an object in one of the
> sub lists -- changes all the objects in the other sub lists.
>
> I'm sure you're not going to find it -- and even if you do, it's going to be
> 1 program in 1000's.

Per the last thread where we discussed extremely rare scenarios,
shouldn't you be rounding "1 in 1000s" up to 20%? ;-)

[toc] | [prev] | [next] | [standalone]


#32836

From"Prasad, Ramit" <ramit.prasad@jpmorgan.com>
Date2012-11-06 17:32 +0000
Message-ID<mailman.3334.1352223730.27098.python-list@python.org>
In reply to#32762
Ian Kelly wrote:
> 
> On Tue, Nov 6, 2012 at 1:21 AM, Andrew Robinson
> 
[snip]
> > See if you can find *any* python program where people desired the
> > multiplication to have the die effect that changing an object in one of the
> > sub lists -- changes all the objects in the other sub lists.
> >
> > I'm sure you're not going to find it -- and even if you do, it's going to be
> > 1 program in 1000's.
> 
> Per the last thread where we discussed extremely rare scenarios,
> shouldn't you be rounding "1 in 1000s" up to 20%? ;-)

Actually, I would be surprised if it was even 1 in 1000.
Of course, consistency makes it easier to learn and *remember*. 
I value that far more than a minor quirk that is unlikely to 
bother me now that I know of it. Well, at least not as long as 
I do not forget my morning coffee/tea :)


~Ramit


This email is confidential and subject to important disclaimers and
conditions including on offers for the purchase or sale of
securities, accuracy and completeness of information, viruses,
confidentiality, legal privilege, and legal entity disclaimers,
available at http://www.jpmorgan.com/pages/disclosures/email.  

[toc] | [prev] | [next] | [standalone]


#32842

FromAndrew Robinson <andrew3@r3dsolutions.com>
Date2012-11-06 13:14 -0800
Message-ID<mailman.3339.1352236812.27098.python-list@python.org>
In reply to#32762
On 11/06/2012 06:35 AM, Oscar Benjamin wrote:
>
> > In general, people don't use element multiplication (that I have 
> *ever* seen) to make lists where all elements of the outer most list 
> point to the same sub-*list* by reference.  The most common use of the 
> multiplication is to fill an array with a constant, or short list of 
> constants;  Hence, almost everyone has  to work around the issue as 
> the initial poster did by using a much longer construction.
>
> That's what I have seen as well. I've never seen an example where 
> someone wanted this behaviour.
>
> >
> > The most compact notation in programming really ought to reflect the 
> most *commonly* desired operation.  Otherwise, we're really just 
> making people do extra typing for no reason.
>
> It's not so much the typing as the fact that this a common gotcha. 
> Apparently many people expect different behaviour here. I seem to 
> remember finding this surprising at first.
>
:)  That's true as well.
>
> >
> > Further, list comprehensions take quite a bit longer to run than low 
> level copies; by a factor of roughly 10. SO, it really would be worth 
> implementing the underlying logic -- even if it wasn't super easy.
> >
> > I really don't think doing a shallow copy of lists would break 
> anyone's program.
> > The non-list elements, whatever they are, can be left as reference 
> copies -- but any element which is a list ought to be shallow copied. 
>  The behavior observed in the opening post where modifying one element 
> of a sub-list, modifies all elements of all sub-lists is never desired 
> as far as I have ever witnessed.
>
> It is a semantic change that would, I imagine, break many things in 
> subtle ways.
>
?? Do you have any guesses, how ?
>
> >
> > The underlying implementation of Python can check an object type 
> trivially, and the only routine needed is a shallow list copy.  So, no 
> it really isn't a complicated operation to do shallow copies of lists.
>
> Yes but if you're inspecting the object to find out whether to copy it 
> what do you test for? If you check for a list type what about 
> subclasses? What if someone else has a custom list type that is not a 
> subclass? Should there be a dunder method for this?
>
No dunder methods.  :)
Custom non-subclass list types aren't a common usage for list 
multiplication in any event.
At present one has to do list comprehensions for that, and that would 
simply remain so.

Subclasses, however, are something I hadn't considered...

> I don't think it's such a simple problem.
>
> Oscar
>
You made a good point, Oscar; I'll have to think about the subclassing a 
bit.
:)

[toc] | [prev] | [next] | [standalone]


#32843

FromAndrew Robinson <andrew3@r3dsolutions.com>
Date2012-11-06 13:19 -0800
Message-ID<mailman.3340.1352237153.27098.python-list@python.org>
In reply to#32762
On 11/06/2012 09:32 AM, Prasad, Ramit wrote:
> Ian Kelly wrote:
>> On Tue, Nov 6, 2012 at 1:21 AM, Andrew Robinson
>>
> [snip]
>>> See if you can find *any* python program where people desired the
>>> multiplication to have the die effect that changing an object in one of the
>>> sub lists -- changes all the objects in the other sub lists.
>>>
>>> I'm sure you're not going to find it -- and even if you do, it's going to be
>>> 1 program in 1000's.
>> Per the last thread where we discussed extremely rare scenarios,
>> shouldn't you be rounding "1 in 1000s" up to 20%? ;-)
:D -- Ian -- also consider that I *am* willing to use extra memory.
Not everything can be shrunk to nothing and still remain functional.  :)
So, it isn't *all* about *micro* optimization -- it's also about 
psychology and flexibility.
> Actually, I would be surprised if it was even 1 in 1000.
> Of course, consistency makes it easier to learn and *remember*.
> I value that far more than a minor quirk that is unlikely to
> bother me now that I know of it. Well, at least not as long as
> I do not forget my morning coffee/tea :)
But, having it copy lists -- when the only purpose of multiplication is 
for lists;
is only a minor quirk as well.

>
>
> ~Ramit

[toc] | [prev] | [next] | [standalone]


#32844

FromIan Kelly <ian.g.kelly@gmail.com>
Date2012-11-06 15:46 -0700
Message-ID<mailman.3342.1352242045.27098.python-list@python.org>
In reply to#32762
On Tue, Nov 6, 2012 at 2:36 PM, Andrew Robinson
<andrew3@r3dsolutions.com> wrote:
> I meant all lists are shallow copied from the innermost level out.
> Equivalently, it's a deep copy of list objects -- but a shallow copy of any list contents except other lists.

Why only list objects, though?  When a user writes [[]] * 10, they
probably want a list containing ten distinct nested lists.  Likewise,
when a user writes [{}] * 10, they probably want a list containing ten
distinct dicts, which is not at all an uncommon thing to want.  It
seems very inconsistent that the former should work while the latter
should not.  This is especially true when you start mixing the two
paradigms; the user might expect [[{}] * 10] * 10 to create a a 10x10
matrix where each element is a distinct dict, but this still would not
work, even though the nested lists would all have different
identities.

What about ([],) * 10?  This is perhaps best interpreted as a request
to create a matrix of ten rows where the rows themselves are mutable
but the collection of rows is not.  If list multiplication were to
copy nested lists, then should tuple multiplication do the same?

[toc] | [prev] | [next] | [standalone]


#32870

FromGregory Ewing <greg.ewing@canterbury.ac.nz>
Date2012-11-07 18:34 +1300
Message-ID<afua6hFbj9gU2@mid.individual.net>
In reply to#32844
If anything is to be done in this area, it would be better
as an extension of list comprehensions, e.g.

   [[None times 5] times 10]

which would be equivalent to

   [[None for _i in xrange(5)] for _j in xrange(10)]

-- 
Greg

[toc] | [prev] | [next] | [standalone]


#32886

FromOscar Benjamin <oscar.j.benjamin@gmail.com>
Date2012-11-07 14:00 +0000
Message-ID<mailman.3371.1352296829.27098.python-list@python.org>
In reply to#32870
On 7 November 2012 13:39, Joshua Landau <joshua.landau.ws@gmail.com> wrote:
>
> On 7 November 2012 11:11, Oscar Benjamin <oscar.j.benjamin@gmail.com> wrote:
>>
>> A more modest addition for the limited case described in this thread could
>> be to use exponentiation:
>>
>> >>> [0] ** (2, 3)
>> [[0, 0, 0], [0, 0, 0]]
>
> Hold on: why not just use multiplication?
>
>>>> [0] * (2, 3)
>
> is an error now, and it makes total sense. Additionally, it's not breaking
> the "no copy -- _ever_" rule because none of the lists existed before. The
> values inside the list would be by reference, as before, so lst * (x,) would
> be the same as lst * x if x is an integer.

The problem is that this operation is asymmetric. Currently int/list
multiplication is commutative so that:

['a', 'b'] * 2 == 2 * ['a', 'b']

If you use this kind of multiplication what happens to the other
cases? e.g. what do you give for:

>>> [0] * [2, 3]

>>> [2, 3] * [0]

>>> (2, 3) * [0]

>>> (2, 3) * (4, 5)

and so on. Although Python does not guarantee commutativity of
multiplication in general I think that since for lists it has always
been commutative it would be bad to change that.

Exponentiation is expected to be asymmetric and is currently unused so
there is no ambiguity. The problem is if someone has already
subclassed list and added an exponentiation method.


Oscar

[toc] | [prev] | [next] | [standalone]


#32889

FromEthan Furman <ethan@stoneleaf.us>
Date2012-11-07 06:47 -0800
Message-ID<mailman.3373.1352303560.27098.python-list@python.org>
In reply to#32870
Oscar Benjamin wrote:
> On Nov 7, 2012 5:41 AM, "Gregory Ewing" <greg.ewing@canterbury.ac.nz 
> <mailto:greg.ewing@canterbury.ac.nz>> wrote:
>  >
>  > If anything is to be done in this area, it would be better
>  > as an extension of list comprehensions, e.g.
>  >
>  >   [[None times 5] times 10]
>  >
>  > which would be equivalent to
>  >
>  >   [[None for _i in xrange(5)] for _j in xrange(10)]
> 
> I think you're right that the meaning of list-int multiplication 
> can't/shouldn't be changed if this way.
> 
> A multidimensional list comprehension would be useful even for people 
> who are using numpy as it's common to use a list comprehension to 
> initialise a numpy array.
> 
> A more modest addition for the limited case described in this thread 
> could be to use exponentiation:
> 
>  >>> [0] ** (2, 3)
> [[0, 0, 0], [0, 0, 0]]

What would happen with

--> [{}] ** (2, 3)

or

--> [my_custom_container()] ** (2, 3)

?

~Ethan~

[toc] | [prev] | [next] | [standalone]


#32911

FromOscar Benjamin <oscar.j.benjamin@gmail.com>
Date2012-11-07 23:06 +0000
Message-ID<mailman.3399.1352329595.27098.python-list@python.org>
In reply to#32870
On 7 November 2012 22:16, Joshua Landau <joshua.landau.ws@gmail.com> wrote:
> On 7 November 2012 14:00, Oscar Benjamin <oscar.j.benjamin@gmail.com> wrote:
>> On 7 November 2012 13:39, Joshua Landau <joshua.landau.ws@gmail.com>
>> wrote:
>> > On 7 November 2012 11:11, Oscar Benjamin <oscar.j.benjamin@gmail.com>
>> > wrote:
>> >> A more modest addition for the limited case described in this thread
>> >> could
>> >> be to use exponentiation:
>> >>
>> >> >>> [0] ** (2, 3)
>> >> [[0, 0, 0], [0, 0, 0]]
>>
>> Exponentiation is expected to be asymmetric and is currently unused so
>> there is no ambiguity. The problem is if someone has already
>> subclassed list and added an exponentiation method.
>
> How is that a problem? They just wont get the functionality.

This is absolutely contrived but:
Library A defines a subclass of list that adds an exponentiation
operator thinking that it's okay to still use these objects as lists.
Library B has an API that expects a list and tries to use the list
copy-exponentiation on its input. A user passes a list type object
from library A into library B and hopefully gets an error but possibly
gets a subtle bug that is hard to track down.

It doesn't sound plausible to me but at least in principle there is a
backward compatibility problem.

> That said, losing:
> [0] * (2, 3) == [0] * [2, 3]
> would mean losing duck-typing in general. *Thus*, I fully agree with your
> choice of exponentiation.

Also there's no reason why tuples couldn't have the same
exponentiation operator (although for them it would be no different
from repeated multiplication).


Oscar

[toc] | [prev] | [next] | [standalone]


#32928

FromGreg Ewing <greg.ewing@canterbury.ac.nz>
Date2012-11-08 14:29 +1300
Message-ID<mailman.3417.1352338205.27098.python-list@python.org>
In reply to#32870
On 08/11/12 12:06, Oscar Benjamin wrote:
> On 7 November 2012 22:16, Joshua Landau<joshua.landau.ws@gmail.com>  wrote:
>> That said, losing:
>> [0] * (2, 3) == [0] * [2, 3]
>> would mean losing duck-typing in general.

There are precedents for this kind of thing; the
string % operator treats tuples specially, for
example.

I don't think it's all that bad if you regard
the tuple as effectively part of the syntax.

-- 
Greg

[toc] | [prev] | [next] | [standalone]


#32763

Fromwxjmfauth@gmail.com
Date2012-11-05 01:55 -0800
Message-ID<d5a065c4-163a-416f-b75d-f73ce66ec35c@googlegroups.com>
In reply to#32748
Le lundi 5 novembre 2012 07:28:00 UTC+1, Demian Brecht a écrit :
> So, here I was thinking "oh, this is a nice, easy way to initialize a 4D matrix" (running 2.7.3, non-core libs not allowed):
> 
> 
> 
> m = [[None] * 4] * 4
> 
> 
> 
> The way to get what I was after was:
> 
> 
> 
> m = [[None] * 4, [None] * 4, [None] * 4, [None * 4]] 
> 
> 
> 
> (Obviously, I could have just hardcoded the initialization, but I'm too lazy to type all that out ;))
> 
> 
> 
> The behaviour I encountered seems a little contradictory to me. [None] * 4 creates four distinct elements in a single array while [[None] * 4] * 4 creates one distinct array of four distinct elements, with three references to it:
> 
> 
> 
> >>> a = [None] * 4
> 
> >>> a[0] = 'a'
> 
> >>> a
> 
> ['a', None, None, None]
> 
> 
> 
> >>> m = [[None] * 4] * 4
> 
> >>> m[0][0] = 'm'
> 
> >>> m
> 
> [['m', None, None, None], ['m', None, None, None], ['m', None, None, None], ['m', None, None, None]]
> 
> 
> 
> Is this expected behaviour and if so, why? In my mind either result makes sense, but the inconsistency is what throws me off.
> 
> 
> 
> Demian Brecht
> 
> @demianbrecht
> 
> http://demianbrecht.github.com

----------

You probably mean a two-dimensional matrix not a 4D matrix.

>>> def DefMatrix(nrow, ncol, val):
...     return [[val] * ncol for i in range(nrow)]
...     
>>> aa = DefMatrix(2, 3, 1.0)
>>> aa
>>> aa = DefMatrix(2, 3, 1.0)
>>> aa
[[1.0, 1.0, 1.0], [1.0, 1.0, 1.0]]
>>> aa[0][0] = 3.14
>>> aa[1][2] = 2.718
>>> aa
[[3.14, 1.0, 1.0], [1.0, 1.0, 2.718]]
>>> 
>>> bb = DefMatrix(2, 3, None)
>>> bb
[[None, None, None], [None, None, None]]
>>> bb[0][0] = 3.14
>>> bb[1][2] = 2.718
>>> bb
[[3.14, None, None], [None, None, 2.718]]


jmf

[toc] | [prev] | [standalone]


Page 3 of 3 — ← Prev page 1 2 [3]

Back to top | Article view | comp.lang.python


csiph-web