Account Options

  1. Sign in
The old Google Groups will be going away soon, but your browser is incompatible with the new version.
Google Groups Home
« Groups Home
Multi-dimensional list initialization
There are currently too many topics in this group that display first. To make this topic appear first, remove this option from another topic.
There was an error processing your request. Please try again.
flag
  Messages 26 - 50 of 67 - Collapse all  -  Translate all to Translated (View all originals) < Older  Newer >
The group you are posting to is a Usenet group. Messages posted to this group will make your email address visible to anyone on the Internet.
Your reply message has not been sent.
Your post was successful
 
From:
To:
Cc:
Followup To:
Add Cc | Add Followup-to | Edit Subject
Subject:
Validation:
For verification purposes please type the characters you see in the picture below or the numbers you hear by clicking the accessibility icon. Listen and type the numbers you hear
 
Ian Kelly  
View profile  
 More options Nov 6 2012, 6:52 pm
Newsgroups: comp.lang.python
From: Ian Kelly <ian.g.ke...@gmail.com>
Date: Tue, 6 Nov 2012 16:52:00 -0700
Subject: Re: Multi-dimensional list initialization
On Tue, Nov 6, 2012 at 3:41 PM, Andrew Robinson

The objection is not nonsense; you've merely misconstrued it.  If
[[1,2,3]] * 4 is expected to create a mutable matrix of 1s, 2s, and
3s, then one would expect [[{}]] * 4 to create a mutable matrix of
dicts.  If the dicts are not copied, then this fails for the same
reason

>>      Q: How about if I use delegation to proxy a list?
>>      A: Oh no, they definitely won't be copied.

> Give an example usage of why someone would want to do this.  Then we can
> discuss it.

Seriously?  Read a book on design patterns.  You might start at SO:

http://stackoverflow.com/questions/832536/when-to-use-delegation-inst...

>> Losing consistency in favour of saving a few characters for something as
>> uncommon as list multiplication is a poor tradeoff. That's why this
>> proposal has been rejected again and again and again every time it has
>> been suggested.

> Please link to the objection being proposed to the developers, and their
> reasoning for rejecting it.
> I think you are exaggerating.
>From Google:

http://bugs.python.org/issue1408
http://bugs.python.org/issue12597
http://bugs.python.org/issue9108
http://bugs.python.org/issue7823

Note that in two out of these four cases, the reporter was trying to
multiply lists of dicts, not just lists of lists.

> Besides, 2D arrays are *not* rare and people *have* to copy internals of
> them very often.
> The copy speed will be the same or *faster*, and the typing less -- and the
> psychological mistakes *less*, the elegance more.

List multiplication is not potentially useful for copying 2D lists,
only for initializing them.  For copying an existing nested list,
you're still stuck with either copy.deepcopy() or a list
comprehension.

> It's hardly going to confuse anyone to say that lists are copied with list
> multiplication, but the elements are not.

> Every time someone passes a list to a function, they *know* that the list is
> passed by value -- and the elements are passed by reference.  People in
> Python are USED to lists being "the" way to weird behavior that other
> languages don't do.

Incorrect.  Python uses what is commonly known as call-by-object, not
call-by-value or call-by-reference.  Passing the list by value would
imply that the list is copied, and that appends or removes to the list
inside the function would not affect the original list.  This is not
what Python does; the list inside the function and the list passed in
are the same list.  At the same time, the function does not have
access to the original reference to the list and cannot reassign it by
reassigning its own reference, so it is not call-by-reference
semantics either.

 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
MRAB  
View profile  
 More options Nov 6 2012, 7:26 pm
Newsgroups: comp.lang.python
From: MRAB <pyt...@mrabarnett.plus.com>
Date: Wed, 07 Nov 2012 00:23:44 +0000
Local: Tues, Nov 6 2012 7:23 pm
Subject: Re: Multi-dimensional list initialization
On 2012-11-06 23:52, Ian Kelly wrote:

I prefer the term "reference semantics".

 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Steven D'Aprano  
View profile  
 More options Nov 6 2012, 8:55 pm
Newsgroups: comp.lang.python
From: Steven D'Aprano <steve+comp.lang.pyt...@pearwood.info>
Date: 07 Nov 2012 01:55:10 GMT
Local: Tues, Nov 6 2012 8:55 pm
Subject: Re: Multi-dimensional list initialization

On Tue, 06 Nov 2012 14:41:24 -0800, Andrew Robinson wrote:
> Yes.  But this isn't going to cost any more time than figuring out
> whether or not the list multiplication is going to cause quirks, itself.
>  Human psychology *tends* (it's a FAQ!) to automatically assume the
> purpose of the list multiplication is to pre-allocate memory for the
> equivalent (using lists) of a multi-dimensional array.  Note the OP even
> said "4d array".

I'm not entirely sure what your point is here. The OP screwed up -- he
didn't generate a 4-dimensional array. He generated a 2-dimensional
array. If his intuition about the number of dimensions is so poor, why
should his intuition about list multiplication be treated as sacrosanct?

As they say, the only truly intuitive interface is the nipple. There are
many places where people's intuition about programming fail. And many
places where Fred's intuition is the opposite of Barney's intuition.

Even more exciting, there are places where people's intuition is
*inconsistent*, where they expect a line of code to behave differently
depending on their intention, rather than on the code. And intuition is
often sub-optimal: e.g. isn't it intuitively obvious that "42" + 1 should
give 43? (Unless it is intuitively obvious that it should give 421.)

So while I prefer intuitively obvious behaviour where possible, it is not
the holy grail, and I am quite happy to give it up.

> The OP's original construction was simple, elegant, easy to read and
> very commonly done by newbies learning the language because it's
> *intuitive*.  His second try was still intuitive, but less easy to read,
> and not as elegant.

Yes. And list multiplication is one of those areas where intuition is
suboptimal -- it produces a worse outcome overall, even if one minor use-
case gets a better outcome.

I'm not disputing that [[0]*n]*m is intuitively obvious and easy. I'm
disputing that this matters. Python would be worse off if list
multiplication behaved intuitively.

An analogy: the intuitively obvious thing to do with a screw is to bang
it in with a hammer. It's long, thin, has a point at the end, and a flat
head that just screams "hit me". But if you do the intuitive thing, your
carpentry will be *much worse* than the alternatives -- a hammered in
screw holds much less strongly than either a nail or a screwed in screw.
The surface area available for gripping is about 2% compared to a nail
and about 0.01% compared to a screw used correctly.

Having list multiplication copy has consequences beyond 2D arrays. Those
consequences make the intuitive behaviour you are requesting a negative
rather than a positive. If that means that newbie programmers have to
learn not to hammer screws in, so be it. It might be harder, slower, and
less elegant to drill a pilot hole and then screw the screw in, but the
overall result is better.

>> * Consistency of semantics is better than a plethora of special
>>    cases. Python has a very simple and useful rule: objects should not
>>    be copied unless explicitly requested to be copied. This is much
>>    better than having to remember whether this operation or that
>>    operation makes a copy. The answer is consistent:

> Bull.  Even in the last thread I noted the range() object produces
> special cases.
>  >>> range(0,5)[1]
> 1
>  >>> range(0,5)[1:3]
> range(1, 3)

What's the special case here? What do you think is copied?

You take a slice of a tuple, you get a new tuple.

You take a slice of a list, you get a new list.

You take a slice of a range object, you get a new range object.

I'm honestly not getting what you think is inconsistent about this.

> The principle involved is that it gives you what you *usually* want;

Who is the "you" that decides what "you" usually want? And how do they
know what is "usual"?

Two-dimensional arrays in Python using lists are quite rare. Anyone who
is doing serious numeric work where they need 2D arrays is using numpy,
not lists. There are millions of people using Python, so it's hardly
surprising that once or twice a year some newbie trips over this. But
it's not something that people tend to trip over again and again and
again, like C's "assignment is an expression" misfeature.

> I read some of the documentation on why Python 3 chose to implement it
> this way.

What documentation is this? Because this is a design decision that goes
all the way back to at least Python 1.5:

[steve@ando ~]$ python1.5
Python 1.5.2 (#1, Aug 27 2012, 09:09:18)  [GCC 4.1.2 20080704 (Red Hat
4.1.2-52)] on linux2
Copyright 1991-1995 Stichting Mathematisch Centrum, Amsterdam

>>> x = [[0]*5]*3
>>> x[0][1] = 99
>>> x

[[0, 99, 0, 0, 0], [0, 99, 0, 0, 0], [0, 99, 0, 0, 0]]

So I expect the design decision for Python 3 was "we made the right
decision before, there's no need to change it".

>>    (pardon me for belabouring the point here)

>>      Q: Does [0]*10 make ten copies of the integer object? A: No, list
>>      multiplication doesn't make copies of elements.

> Neither would my idea for the vast majority of things on your first
> list.

Um, yes? The point is that "vast majority" is not "everything". Hence,
your suggested behaviour is inconsistent.

>      Q: What about [[]]*10?
>      A: No, the elements are never copied.

> YES! For the obvious reason that such a construction is making mutable
> lists that the user wants to populate later.  If they *didn't* want to
> populate them later, they ought to have used tuples -- which take less
> overhead.  Who even does this thing you are suggesting?!

Who knows? Who cares? Nobody does:

n -= n

instead of just n=0, but that doesn't mean that we should give it some
sort of special meaning different from n -= m. If it turns out that the
definition of list multiplication is such that NOBODY, EVER, uses [[]]*n,
that is *still* not a good reason for special-casing it. All it means is
that this will be a less-obscure example of the billions of things which
can be done in Python but nobody wants to.

You have quoted from the Zen of Python a few times in this post. Perhaps
you missed one of the most critical ones?

Special cases aren't special enough to break the rules.

There are perfectly good ways to generate a 2D array out of lists, and
even better reasons not to use lists for that in the first place. (Numpy
arrays are much better suited for serious work.)

>>      Q: What about other mutable objects like sets or dicts? A: No, the
>>      elements are never copied.

> They aren't list multiplication compatible in any event! It's a total
> nonsense objection.

I'm afraid you've just lost an awful lot of credibility there.

py> x = [{}]*5
py> x
[{}, {}, {}, {}, {}]
py> x[0]['key'] = 1
py> x
[{'key': 1}, {'key': 1}, {'key': 1}, {'key': 1}, {'key': 1}]

And similarly for any other mutable object.

If you don't understand that lists can contain other mutable objects
apart from lists, then you really shouldn't be discussing this issue.

>> Your proposal throws away consistency for a trivial benefit on a rare
>> use- case, and replaces it with a bunch of special cases:

> RARE!!!! You are NUTS!!!!

Yes, rare. I base that on about 15 years of Python coding and many
thousands (tens of thousands?) of hours on Python forums like this one.
What's your opinion based on?

List multiplication is rare enough, but when it is used, it is usually
used to generate a 1D array like this:

values = [None]*n  # or 0 is another popular starting value

Using it twice to generate a 2D array is even rarer.

>>      Q: How about if I use delegation to proxy a list? A: Oh no, they
>>      definitely won't be copied.

> Give an example usage of why someone would want to do this.  Then we can
> discuss it.

Proxying objects is hardly a rare scenario. Delegation is less common
since you can subclass built-ins, but it is still used. It is a standard
design pattern.

>> Losing consistency in favour of saving a few characters for something
>> as uncommon as list multiplication is a poor tradeoff. That's why this
>> proposal has been rejected again and again and again every time it has
>> been suggested.

> Please link to the objection being proposed to the developers, and their
> reasoning for rejecting it.
> I think you are exaggerating.

Python is a twenty year old language. Do you really think this is the
first time somebody has noticed it?

It's hard to search for discussions on the dev list, because the obvious
search terms bring up many false positives. But here are a couple of bug
reports closed as "won't fix":

http://bugs.python.org/issue1408
http://bugs.python.org/issue12597

I suspect it is long past time for a PEP so this can be rejected once and
for all.

>> List multiplication [x]*n is conceptually equivalent to: <snip>
>> This is nice and simple and efficient.
> No it isn't efficient. It's *slow* when done as in your example.

Well of course it is slow*er* when you move it from low-level C to high
level Python, but it is still fast.

>> Copying other objects is slow and inefficient. Keeping list
>> multiplication consistent, and fast, is MUCH more important than making
>> it work as expected for the rare case of 2D arrays:

> I don't think so -- again, look at range(); it was made to work
> inconsistent for a "common" case.

You mentioned range before, but it isn't clear to me what you think is
inconsistent about it.

> Besides, 2D arrays are *not* rare and people *have* to copy internals of
> them very often.

So you say.

> The copy speed will be the same or *faster*, and the typing less -- and
> the psychological mistakes *less*, the elegance more.

You think that it is *faster* to copy a list than to make
...

read more »


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
rusi  
View profile  
 More options Nov 6 2012, 11:11 pm
Newsgroups: comp.lang.python
From: rusi <rustompm...@gmail.com>
Date: Tue, 6 Nov 2012 20:11:45 -0800 (PST)
Local: Tues, Nov 6 2012 11:11 pm
Subject: Re: Multi-dimensional list initialization
On Nov 7, 5:26 am, MRAB <pyt...@mrabarnett.plus.com> wrote:

> I prefer the term "reference semantics".

Ha! That hits the nail on the head.

To go back to the OP:

On Nov 5, 11:28 am, Demian Brecht <demianbre...@gmail.com> wrote:

m=[[None] * 2] * 3

is the same as

m=[[None]*2, [None]*2, [None]*2]

until one starts doing things like

m[0][0] = 'm'

So dont do it!

And to get python to help you by saying the same that I am saying do
m=((None) * 2) * 3
(well almost... its a bit more messy in practice)
m=(((None,) * 2),)*3

After that try assigning to m[0][0] and python will kindly say NO!

tl;dr version:
reference semantics is ok
assignment is ok (well up to a point)
assignment + reference semantics is not


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Steven D'Aprano  
View profile  
 More options Nov 7 2012, 12:05 am
Newsgroups: comp.lang.python
From: Steven D'Aprano <steve+comp.lang.pyt...@pearwood.info>
Date: 07 Nov 2012 05:05:34 GMT
Local: Wed, Nov 7 2012 12:05 am
Subject: Re: Multi-dimensional list initialization

On Wed, 07 Nov 2012 00:23:44 +0000, MRAB wrote:
>> Incorrect.  Python uses what is commonly known as call-by-object, not
>> call-by-value or call-by-reference.  Passing the list by value would
>> imply that the list is copied, and that appends or removes to the list
>> inside the function would not affect the original list.  This is not
>> what Python does; the list inside the function and the list passed in
>> are the same list.  At the same time, the function does not have access
>> to the original reference to the list and cannot reassign it by
>> reassigning its own reference, so it is not call-by-reference semantics
>> either.

> I prefer the term "reference semantics".

Oh good, because what the world needs is yet another name for the same
behaviour.

- call by sharing
- call by object sharing
- call by object reference
- call by object
- call by value, where "values" are references
  (according to the Java community)
- call by reference, where "references" refer to objects, not variables
  (according to the Ruby community)
- reference semantics

Anything else?

http://en.wikipedia.org/wiki/Evaluation_strategy#Call_by_sharing

--
Steven


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Roy Smith  
View profile  
 More options Nov 7 2012, 12:12 am
Newsgroups: comp.lang.python
From: Roy Smith <r...@panix.com>
Date: Wed, 07 Nov 2012 00:12:18 -0500
Local: Wed, Nov 7 2012 12:12 am
Subject: Re: Multi-dimensional list initialization
In article <5099ec1d$0$21759$c3e8da3$76491...@news.astraweb.com>,
 Steven D'Aprano <steve+comp.lang.pyt...@pearwood.info> wrote:

Call by social network?  The called function likes the object.  
Depending on how it feels, it can also comment on some of the object's
attributes.

 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Gregory Ewing  
View profile  
 More options Nov 7 2012, 12:32 am
Newsgroups: comp.lang.python
From: Gregory Ewing <greg.ew...@canterbury.ac.nz>
Date: Wed, 07 Nov 2012 18:32:03 +1300
Local: Wed, Nov 7 2012 12:32 am
Subject: Re: Multi-dimensional list initialization

Roy Smith wrote:
> Call by social network?  The called function likes the object.  
> Depending on how it feels, it can also comment on some of the object's
> attributes.

And then finds that it has inadvertently shared all its
private data with other functions accessing the object.

--
Greg


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Gregory Ewing  
View profile  
 More options Nov 7 2012, 12:34 am
Newsgroups: comp.lang.python
From: Gregory Ewing <greg.ew...@canterbury.ac.nz>
Date: Wed, 07 Nov 2012 18:34:09 +1300
Local: Wed, Nov 7 2012 12:34 am
Subject: Re: Multi-dimensional list initialization
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


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Demian Brecht  
View profile  
 More options Nov 7 2012, 1:56 am
Newsgroups: comp.lang.python
From: Demian Brecht <demianbre...@gmail.com>
Date: Tue, 6 Nov 2012 22:56:33 -0800
Local: Wed, Nov 7 2012 1:56 am
Subject: Re: Multi-dimensional list initialization

On 2012-11-06, at 5:55 PM, Steven D'Aprano <steve+comp.lang.pyt...@pearwood.info> wrote:

> I'm not entirely sure what your point is here. The OP screwed up -- he
> didn't generate a 4-dimensional array. He generated a 2-dimensional
> array. If his intuition about the number of dimensions is so poor, why
> should his intuition about list multiplication be treated as sacrosanct?

Yep, I may have mis-worded the explanation a bit (although I *did* express that it was a 4D matrix in the OP). I was using a 2D list to represent a 4D matrix in order to easily iterate over 90 degree rotations with zip(*matrix[::-1]). It wasn't for production code (otherwise I *would* be using numpy), it was for an online programming challenge in which external libs are not supported.

> As they say, the only truly intuitive interface is the nipple. There are
> many places where people's intuition about programming fail. And many
> places where Fred's intuition is the opposite of Barney's intuition.

I couldn't agree more with this. My question was *not* based on what I perceive to be intuitive (although most of this thread has now seemed to devolve into that and become more of a philosophical debate), but was based on what I thought may have been inconsistent behaviour (which was quickly cleared up with None being immutable and causing it to *seem* that the behaviour was inconsistent to the forgetful mind). As you touch on here, "intuition" is entirely subjective. If you're coming from a C/C++ background, I'd think that your intuition would be that everything's passed by value unless explicitly stated. Someone coming from another background (Lua perhaps?) would likely have entirely different intuition.

> So while I prefer intuitively obvious behaviour where possible, it is not
> the holy grail, and I am quite happy to give it up.

I fail to see where there has been any giving up on intuitiveness in the context of this particular topic. In my mind, intuitiveness is generally born of repetitiveness and consistency. As everything in Python is a reference, it would seem to me to be inconsistent to treat expressions such as [[obj]*4]*4 un-semantically (Pythonically speaking) and making it *less* intuitive. I agree that Python would definitely be worse off.

Demian Brecht
@demianbrecht
http://demianbrecht.github.com


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Jussi Piitulainen  
View profile  
 More options Nov 7 2012, 3:52 am
Newsgroups: comp.lang.python
From: Jussi Piitulainen <jpiit...@ling.helsinki.fi>
Date: 07 Nov 2012 10:52:49 +0200
Local: Wed, Nov 7 2012 3:52 am
Subject: Re: Multi-dimensional list initialization

Something else:

There's a call-by-* versus pass-by-* distinction, where the call-by-*
would be rather different from any of the above:

- call-by-value is what most languages now use: argument expressions
  are reduced to values before they are passed to the function /
  procedure / method / whatever.

- call-by-name was something Algol 60 had by default: something like
  evaluating the argument expression every time its value is needed

- call-by-need: argument expression is reduced to a value the first
  time its value is needed (if ever)

- call-by-lazy (increasingly silly terminology, and I don't quite have
  an idea what it means in contrast to call-by-need)

The modern confusions would then be mostly over the pass-by-* family,
invariably using call-by-value in the above sense. The terminology for
these tends to produce more heat than light, but I think the relevant
distinctions are mostly just these:

- can one modify the argument effectively [Python: yes]

- can one modify the parameter with abandon [Python: don't]

- can one swap [Python: no]

- possibly: is it expensive to pass large objects? [Python: no]

The actual rule in Scheme, Java, and Python is the same simple and
sane rule: what are passed are values (argument expressions are fully
evaluated before the actual call takes place), parameter passing does
not involve any (observable) copying, and the arguments are bound to
fresh variables (no aliasing of variables).

Different communities use different words. Sometimes they use the same
words about different things. Resulting in more heat than light :(

(I'd have a few more things in the something-else department, but this
is already much longer than I thought. Ends.)


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
wxjmfa...@gmail.com  
View profile  
 More options Nov 7 2012, 3:57 am
Newsgroups: comp.lang.python
From: wxjmfa...@gmail.com
Date: Wed, 7 Nov 2012 00:57:29 -0800 (PST)
Local: Wed, Nov 7 2012 3:57 am
Subject: Re: Multi-dimensional list initialization
Le mercredi 7 novembre 2012 02:55:10 UTC+1, Steven D'Aprano a écrit :

--------------------

>>> from vecmat6 import *
>>> from vmio5 import *

Traceback (most recent call last):
  File "<eta last command>", line 1, in <module>
ImportError: No module named vmio5
>>> from vmio6 import *
>>> from svdecomp6 import *
>>> mm = NewMat(3, 3)
>>> mm

[[0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0]]
>>> mm[0][0] = 1.0; mm[0][1] = 2.0; mm[0][2] = 3.0
>>> mm[1][0] = 11.0; mm[1][1] = 12.0; mm[1][2] = 13.0
>>> mm[2][0] = 21.0; mm[2][1] = 22.0; mm[2][2] = 23.0
>>> pr(mm, 'mm=')

mm=
(   1.00000e+000  2.00000e+000  3.00000e+000 )
(   1.10000e+001  1.20000e+001  1.30000e+001 )
(   2.10000e+001  2.20000e+001  2.30000e+001 )
>>> aa, b, cc = SVDecomp(mm)
>>> pr(aa, 'aa=')

aa=
(  -8.08925e-002 -9.09280e-001  4.08248e-001 )
(  -4.77811e-001 -3.24083e-001 -8.16497e-001 )
(  -8.74730e-001  2.61114e-001  4.08248e-001 )
>>> pr(b, 'b=')

b=
(   4.35902e+001  1.37646e+000  1.93953e-016 )
>>> pr(cc, 'cc=')

cc=
(  -5.43841e-001  7.33192e-001  4.08248e-001 )
(  -5.76726e-001  2.68499e-002 -8.16497e-001 )
(  -6.09610e-001 -6.79492e-001  4.08248e-001 )
>>> bb = VecToDiagMat(b)
>>> cct = TransposeMat(cc)
>>> oo = MatMulMatMulMat(aa, bb, cct)
>>> pr(oo, 'aa * bb * cct=')

aa * bb * cct=
(   1.00000e+000  2.00000e+000  3.00000e+000 )
(   1.10000e+001  1.20000e+001  1.30000e+001 )
(   2.10000e+001  2.20000e+001  2.30000e+001 )

>>> # or
>>> oo

[[0.9999999999999991, 1.9999999999999993, 2.9999999999999982],
[10.999999999999995, 11.99999999999999, 12.999999999999996],
[20.999999999999986, 21.999999999999975, 22.999999999999986]]

jmf


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Oscar Benjamin  
View profile  
 More options Nov 7 2012, 9:00 am
Newsgroups: comp.lang.python
From: Oscar Benjamin <oscar.j.benja...@gmail.com>
Date: Wed, 7 Nov 2012 14:00:27 +0000
Local: Wed, Nov 7 2012 9:00 am
Subject: Re: Multi-dimensional list initialization
On 7 November 2012 13:39, Joshua Landau <joshua.landau...@gmail.com> wrote:

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


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Ethan Furman  
View profile  
 More options Nov 7 2012, 10:31 am
Newsgroups: comp.lang.python
From: Ethan Furman <et...@stoneleaf.us>
Date: Wed, 07 Nov 2012 07:23:12 -0800
Local: Wed, Nov 7 2012 10:23 am
Subject: Re: Multi-dimensional list initialization
After this post the only credibility you have left (with me, anyway) is that you seem to be willing
to learn.  So learn the way Python works before you try to reimplement it.

~Ethan~


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Ethan Furman  
View profile  
 More options Nov 7 2012, 9:47 am
Newsgroups: comp.lang.python
From: Ethan Furman <et...@stoneleaf.us>
Date: Wed, 07 Nov 2012 06:47:53 -0800
Local: Wed, Nov 7 2012 9:47 am
Subject: Re: Multi-dimensional list initialization

What would happen with

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

or

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

?

~Ethan~


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Prasad, Ramit  
View profile  
 More options Nov 7 2012, 10:58 am
Newsgroups: comp.lang.python
From: "Prasad, Ramit" <ramit.pra...@jpmorgan.com>
Date: Wed, 7 Nov 2012 15:57:38 +0000
Local: Wed, Nov 7 2012 10:57 am
Subject: RE: Multi-dimensional list initialization

Gregory Ewing wrote:

> Roy Smith wrote:
> > Call by social network?  The called function likes the object.
> > Depending on how it feels, it can also comment on some of the object's
> > attributes.

> And then finds that it has inadvertently shared all its
> private data with other functions accessing the object.

And this is where Dihedral 8888 (or whatever the bot is called)
tells you that Python has no "private" variables. :)

~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.  


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
MRAB  
View profile  
 More options Nov 7 2012, 12:17 pm
Newsgroups: comp.lang.python
From: MRAB <pyt...@mrabarnett.plus.com>
Date: Wed, 07 Nov 2012 17:17:02 +0000
Local: Wed, Nov 7 2012 12:17 pm
Subject: Re: Multi-dimensional list initialization
On 2012-11-07 05:05, Steven D'Aprano 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 ..."?


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Ian Kelly  
View profile  
 More options Nov 7 2012, 4:02 pm
Newsgroups: comp.lang.python
From: Ian Kelly <ian.g.ke...@gmail.com>
Date: Wed, 7 Nov 2012 14:01:19 -0700
Local: Wed, Nov 7 2012 4:01 pm
Subject: Re: Multi-dimensional list initialization
On Wed, Nov 7, 2012 at 12:51 PM, Andrew Robinson

<andr...@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.

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.  Except that it does not work the same way, because when lists
are passed into functions, they are not copied at all.  Nor are are
any of their contents copied, lists or not.  So actually I did address
this point with the "call-by-object" tangent; I just did not
explicitly link it back to your thesis.

> 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.

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.

> In any event:
> All objects in Python are based on pointers; all parameters passed to
> functions, etc, are *copies* of those pointers; (by pointer value).

No, all parameters passed to functions are *objects*.  Python itself
has no concept of pointers.  What you describe is true as an
implementation detail for CPython but not necessarily true for other
implementations, and not true at all for an abstract
(implementation-independent) view of the language.

> I made the distinction between contents of the list and the list object
> itself for that reason; I gave an explicit correction to the pass by "value"
> generalization by saying: ("the elements are passed by reference").

The elements are not passed anywhere.  Only the list object is passed
to the function, which is completely agnostic of the fact that the
list object happens to contain other objects.

 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Mark Lawrence  
View profile  
 More options Nov 7 2012, 5:28 pm
Newsgroups: comp.lang.python
From: Mark Lawrence <breamore...@yahoo.co.uk>
Date: Wed, 07 Nov 2012 22:27:26 +0000
Local: Wed, Nov 7 2012 5:27 pm
Subject: Re: Multi-dimensional list initialization
On 07/11/2012 22:02, Andrew Robinson wrote:


You're doing extremely well, you've overtaken Xah Lee as the biggest
waste of space on this list.

--
Cheers.

Mark Lawrence.


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Steven D'Aprano  
View profile  
 More options Nov 7 2012, 5:36 pm
Newsgroups: comp.lang.python
From: Steven D'Aprano <steve+comp.lang.pyt...@pearwood.info>
Date: 07 Nov 2012 22:36:53 GMT
Local: Wed, Nov 7 2012 5:36 pm
Subject: Re: Multi-dimensional list initialization

On Wed, 07 Nov 2012 17:17:02 +0000, MRAB wrote:
> The disadvantage of calling it "call by ..." is that it suggests that
> you're just talking about calling functions.

*shrug*

There are already two synonyms for this, "call by ..." and "pass by ...".
They are old, venerable terms dating back to Algol and possibly even
older. All the way back to Fortran perhaps?

> What about binding in general, eg "x = y"? Does it make sense to still
> call it "call by ..."?

Sure, why not? The person who prepares beef tartare or sushimi is still
called the cook.

--
Steven


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Oscar Benjamin  
View profile  
 More options Nov 7 2012, 6:06 pm
Newsgroups: comp.lang.python
From: Oscar Benjamin <oscar.j.benja...@gmail.com>
Date: Wed, 7 Nov 2012 23:06:27 +0000
Local: Wed, Nov 7 2012 6:06 pm
Subject: Re: Multi-dimensional list initialization
On 7 November 2012 22:16, Joshua Landau <joshua.landau...@gmail.com> wrote:

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


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Ian Kelly  
View profile  
 More options Nov 7 2012, 6:40 pm
Newsgroups: comp.lang.python
From: Ian Kelly <ian.g.ke...@gmail.com>
Date: Wed, 7 Nov 2012 16:39:55 -0700
Local: Wed, Nov 7 2012 6:39 pm
Subject: Re: Multi-dimensional list initialization
On Wed, Nov 7, 2012 at 3:02 PM, Andrew Robinson

<andr...@r3dsolutions.com> wrote:
> Draw up some use cases for the multiplication operator (I'm calling on your
> experience, let's not trust mine, right?);  What are all the Typical ways
> people *Do* to use it now?

> If those use cases do not *primarily* center around *wanting* an effect
> explicitly caused by reference duplication -- then it may be better to
> abolish list multiplication all together; and rather, improve the list
> comprehensions to overcome the memory, clarity, and speed pitfalls in the
> most common case of initializing a list.

Why?  Just to get rid of an FAQ?

Here's one of the more interesting uses from my own code:

    values = zip(samples, times * num_groups)
    if len(values) < len(times) * num_groups:
        # raise an error

Converting that multiplication to a generator expression would look like this:

    values = zip(samples, (t for _ in range(num_groups) for t in times))

That's not particularly hairy, but I do assert that it is
substantially less readable, and more so because it loses the symmetry
with the following if condition.

The recipes in the itertools docs also include this example, which
notably depends on the list containing multiple references to the same
iterator:

def grouper(n, iterable, fillvalue=None):
    "Collect data into fixed-length chunks or blocks"
    # grouper(3, 'ABCDEFG', 'x') --> ABC DEF Gxx
    args = [iter(iterable)] * n
    return izip_longest(fillvalue=fillvalue, *args)

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.

> For example, in initialization use cases; often the variable of a for loop
> isn't needed and all the initializers have parameters which only need to be
> evaluated *once* (no side effects).

> Hence, there is an opportunity for speed and memory gains,while maintaining
> clarity and *consistency*.

> Some ideas of use cases:
> [ (0) in xrange(10) ]  # The function to create a tuple cache's the
> parameter '0', makes 10 (0)'s
> [ dict.__new__(dict) in xrange(10) ]  # dict.__new__, The dict parameter is
> cached -- makes 10 dicts.
> [ lambda x:(0) in xrange(10) ] # lambda caches (0), returns a *reference* to
> it multiple times.

How exactly do you propose to indicate to the compiler which parts of
the expressions are meant to be cached, and which are not?

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.

> Game programmers routinely use 2D lists to represent the screen layout;
> For example, they might use 'b' to represent a brick tile, and 'w' to
> represent a water tile.

In many cases it may be simpler to use a plain list of strings:

screen = [
    "sssss",
    "ssbss",
    "sbbbs",
    "bbbbb",
]

> py> x = [{}]*5
> py> x
> [{}, {}, {}, {}, {}]

> No, I showed what happed when you do {}*3;
> That *DOESN'T* work;  You aren't multiplying the dictionary, you are
> multiplying the LIST of dictionaries.  Very different things.
> You were complaining that my method doesn't multiply them -- well, gee --
> either mine DOES or python DOESN'T.  Double standards are *crap*.

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.

You are the only one talking about applying the multiplication
operator to dicts.

> Huh?
> I'm not yelling any more than you are.  Are ???YOU??? yelling?

Perhaps you're not aware that on the Internet, TYPING IN ALL CAPS is
commonly construed as SHOUTING.

 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Steven D'Aprano  
View profile  
 More options Nov 7 2012, 7:00 pm
Newsgroups: comp.lang.python
From: Steven D'Aprano <steve+comp.lang.pyt...@pearwood.info>
Date: 08 Nov 2012 00:00:50 GMT
Local: Wed, Nov 7 2012 7:00 pm
Subject: Re: Multi-dimensional list initialization
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
> <andr...@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?

--
Steven


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Andrew Robinson  
View profile  
 More options Nov 7 2012, 7:23 pm
Newsgroups: comp.lang.python
From: Andrew Robinson <andr...@r3dsolutions.com>
Date: Wed, 07 Nov 2012 16:24:22 -0800
Local: Wed, Nov 7 2012 7:24 pm
Subject: Re: Multi-dimensional list initialization
On 11/07/2012 01:01 PM, Ian Kelly wrote:
> On Wed, Nov 7, 2012 at 12:51 PM, Andrew Robinson
> <andr...@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.

 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Oscar Benjamin  
View profile  
 More options Nov 7 2012, 7:31 pm
Newsgroups: comp.lang.python
From: Oscar Benjamin <oscar.j.benja...@gmail.com>
Date: Thu, 8 Nov 2012 00:30:53 +0000
Local: Wed, Nov 7 2012 7:30 pm
Subject: Re: Multi-dimensional list initialization
On 8 November 2012 00:00, Steven D'Aprano

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


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Greg Ewing  
View profile  
 More options Nov 7 2012, 8:30 pm
Newsgroups: comp.lang.python
From: Greg Ewing <greg.ew...@canterbury.ac.nz>
Date: Thu, 08 Nov 2012 14:29:59 +1300
Local: Wed, Nov 7 2012 8:29 pm
Subject: Re: Multi-dimensional list initialization
On 08/11/12 12:06, Oscar Benjamin wrote:

> On 7 November 2012 22:16, Joshua Landau<joshua.landau...@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


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Messages 26 - 50 of 67 < Older  Newer >
« Back to Discussions « Newer topic     Older topic »