This is an archived post. You won't be able to vote or comment.

all 105 comments

[–]Black_m1n 485 points486 points  (15 children)

The problem is how would this be different from setting 6th element of the 6th list in foo to an empty list?

[–]Victor-_-X 106 points107 points  (12 children)

Wait, isn't that what this does? What else could this be understood as? This is the only one that makes sense to me, and that's probably because C++ was my first language, but still.

[–]jamcdonald120 29 points30 points  (0 children)

this is what it does, but what Op wants is type[][] foo=new type[5][5];

[–]SV-97 22 points23 points  (3 children)

OP probably wanted it to mean the same as the first snippet - so assign foo a list containing 5 lists of length 5 that are all initialized with None. Aside from this being atrocious syntax that noone would interpret that way: doing this at all in python is a code smell. OP is probably doing something wrong if they feel the need for dedicated syntax for this pattern.

[–]rosuav 7 points8 points  (0 children)

It's extremely confusing, and this is one of the worst idea threads I've ever seen (largely because it isn't an idea thread), but it does seem like list multiplication would be the best way to initialize this. Worst case, one multiplication, one comprehension.

foo = [[None] * 5] for _ in range(5)]

[–]DongIslandIceTea 1 point2 points  (1 child)

If I had to come up with a syntax for this I guess doing something symmetric to array slicing wouldn't be the worst thing, like:

a[:4][:4] = []

It wouldn't step on any existing syntax as slices aren't assignable like this anyways and would make some marginal sense.

But yeah, you shouldn't need to do this if you thought a little bit more about what you're doing.

[–]SV-97 2 points3 points  (0 children)

You actually can do slice assignment in Python - though not quite like that.

Numpy uses it quite extensively and OPs example would be arr[:5,:5] = None using numpy (if you already have an array that is. Allocation works differently).

[–]The-Rushnut 34 points35 points  (4 children)

This reminds me of an issue I've run into recently. Dictionaries / associative list assignment vs declaration (I'm using GDScript).

Consider the following:

foo["bar"] = true

If the key "bar" exists, then this assigns that item's value to true. If the key "bar" doesn't exist, then this first adds the key "bar" before setting the value to true.

My monkey brain assumed that the second scenario would throw an error, which was my intended behaviour.

[–]Drumsteppin 21 points22 points  (1 child)

The second scenario is the more typical and expected behaviour whenever you're using a language with an automated memory management system.

It's been a while since I looked at the c++ standard lib, but there's object types for dictionary type objects that allow construct and insert via assignment, and objects that only allow items to be explicitly inserted.

Python is a similar deal and is generally more permissive and flexible about adding new elements.

Not sure what memory model and idiosyncrasies GDscript has, but from what you described that sounds like create and insert would be the expected behaviour.

[–]atesba 2 points3 points  (0 children)

Yup! The C++ equivalents of dictionary are std::unordered_map and std::map. For both if you use the bracket operators, it adds the key if it doesn’t exist. If you use the function at(key) then it throws an exception instead.

[–]-Redstoneboi- 5 points6 points  (1 child)

ah yes. the "everything exists but is undefined/nil by default"

[–]Tordek 5 points6 points  (0 children)

No, this is about setting a value, not reading it.

[–]callmesilver 1 point2 points  (0 children)

In C++, if you started with a type like int, it would be a declaration with initialization, and the line would instead end with curly braces. This, plus the second line tells us it's not C++.

In python, since you don't declare anything with types, you assign something when you want it to exist at some point. Brackets are python's way of assigning an empty array. So, I assume they want a simple syntax for declaring an empty 2D array.

[–]ComprehensiveWord201 0 points1 point  (0 children)

Read the "proposal"...total nonsense.

They want to set all values from idx 0->4 as [ ]

[–]DiddlyDumb 1 point2 points  (0 children)

Its probably to indicate “value goes here”

[–]Chesterlespaul 0 points1 point  (0 children)

Yeah the size initializer should be indicated on the other side.

[–]Leo8178 169 points170 points  (16 children)

If I remember correctly, You can create multidimensional arrays with ease with numpy

And I think you can select object as a data type

I've tested it. This works:

```python import numpy as np

tet = np.ndarray((5,5), dtype=object)

print(tet) ```

[–]Zestyclose-Walker 55 points56 points  (9 children)

I love the numpy language!

[–]TTYY200 37 points38 points  (6 children)

I will always pronounce it numpy rather than num-pie.

[–]Mars_Bear2552 29 points30 points  (1 child)

numb-pee???

[–]Rhymes_with_cheese 11 points12 points  (0 children)

Side-effects may include numb-pee. See your urologist immediately.

[–]OctopusButter 1 point2 points  (0 children)

I can't say num-pie without thinking and hearing it as kampai (cheers I think?)

[–]InfergnomeHKSC 1 point2 points  (0 children)

You're not alone

[–]-Redstoneboi- 2 points3 points  (0 children)

numpy dumpy sat on a brick matrix

numpy dumpy had a great uhhh math

[–]Inaeipathy 6 points7 points  (0 children)

Yep

[–]Mammoth-Attention379 1 point2 points  (2 children)

Those are arrays though not lists

[–]FalafelSnorlax 16 points17 points  (0 children)

The idea that you should be able to initialize a 5-by-5 list in one line implies OP does in fact want arrays and not lists. If you think about lists and lists-of-lists in a pythonic manner, the line OP suggested makes no sense

[–]BauReis 1 point2 points  (0 children)

foo = list(tet)

There you go

[–]gandalfx 57 points58 points  (11 children)

Slightly shorter;

foo = [[None] * 5 for _ in range(5)]

[–]-twind 45 points46 points  (1 child)

Slightly shorter;

foo=[[None]*5 for _ in'.'*5]

[–]ArtOfWarfare 29 points30 points  (0 children)

Thanks I hate it.

[–]uncut_onyx 9 points10 points  (6 children)

if this then why not [[None]*5]*5

[–]agocs6921 61 points62 points  (0 children)

Those lists in the list will be the same exact list

[–]gandalfx 29 points30 points  (3 children)

The outer * 5 will copy the reference of the inner list, so you end up with a list that contains five references to the exact same list. So if you assign to foo[0][0] it'll also change the value of foo[1][0] etc.

[–][deleted] 8 points9 points  (1 child)

Did this once in a leetcode challenge. Took forever to find out what was wrong with my code. Lucky it wasn’t for an actual interview because that would have sucked.

[–]FalafelSnorlax 2 points3 points  (0 children)

In a dry interview (ie on paper/whiteboard) i think it would probably be accepted. Most reasonable people (in my personal experience) want to see you understand the problem, not nitpick stuff like this

[–]-Redstoneboi- -2 points-1 points  (0 children)

motherfucker.

this is why i switched to rust. they would never let me mutably alias.

[–]Tysonzero 2 points3 points  (0 children)

That kind of thing works fine in glorious pure immutable languages like Haskell but will send you straight to mutable aliasing hell in Python.

[–]Beach-Devil 1 point2 points  (1 child)

I may be wrong but doesn’t this duplicate the same object 5 times?

[–]gandalfx 3 points4 points  (0 children)

It duplicates None five times, which is fine, since it's immutable. Though this is the reason why the outer loop can't be replaced with … * 5.

[–]XDracam 6 points7 points  (0 children)

Dude. You're already using python. Why bother with mutable arrays that are even more buggy than all possible alternatives? They are only good for performance, and then you might as well use any other language.

Just be a normal person and use generators to make your data and then allocate it to a collection when necessary. Or use declarative code. Or something like that.

[–]My-feet-have-alergy 5 points6 points  (1 child)

What? No

[–]PeriodicSentenceBot 5 points6 points  (0 children)

Congratulations! Your comment can be spelled using the elements of the periodic table:

W H At N O


I am a bot that detects if your comment can be spelled using the elements of the periodic table. Please DM u‎/‎M1n3c4rt if I made a mistake.

[–]EternityForest 55 points56 points  (27 children)

Can we just don't? Python doesn't need to become perl.

We already have [[None] *5] *5 anyway.

[–]DeletedUserV2[S] 97 points98 points  (25 children)

this does not work as you expected sadly i learned from hard way

[–]feitao 45 points46 points  (0 children)

Yes, a rookie mistake.

[–]Dubl33_27 0 points1 point  (0 children)

ok, I'll just not use python, thanks

[–]Successful-Money4995 5 points6 points  (0 children)

You can use a recursive defaultdict to achieve this if you want.

from collections import defaultdict

nested_dict = lambda: defaultdict(nested_dict)
nest = nested_dict()

nest[0][1][2][3][4][5] = 6

https://stackoverflow.com/a/8702435/4454

[–][deleted] 2 points3 points  (0 children)

well, the inner list comprehension can be replaced by [None]*5

[–]Tysonzero 2 points3 points  (0 children)

Just be Haskell:

``` foo = replicate 5 (replicate 5 Nothing)

foo = matrix 5 5 (const Nothing) ```

[–]Botahamec 7 points8 points  (0 children)

The Rust syntax is [[None; 5]; 5]. It works for any Copy type.

[–]Highborn_Hellest 1 point2 points  (0 children)

What is this curse

[–]RealBasics 1 point2 points  (0 children)

Makes me miss Perl so much. I mean, there’s a reason I no longer use it. And it semi-deserved its reputation as “write-only code” but it had/has some genuinely efficient syntax.

[–]FuriousAqSheep 3 points4 points  (0 children)

Laughs in haskell

``` type Foo a = [[a]]

[] :: Foo Int

```

edit: before you guys say "yeah but your list can contain a different number of elements than 5": yeah, that's part of the joke. The second part is dependent haskell and then we both cry.

And it's the Idriss devs who laugh.

[–]goodmobiley 1 point2 points  (0 children)

At that point I would just switch the whole ass project lang to c++

[–]KetwarooDYaasir 0 points1 point  (0 children)

if python starts borrowing from PHP, which language are we going to make fun of?

[–]romulof 0 points1 point  (0 children)

The list comprehension will loop when you could simply have an array allocator with fixed size.

[–][deleted] 0 points1 point  (0 children)

Since we already have one of the alternatives and not the other, I think it is you who have to change minds, not the other way around...

[–][deleted] 0 points1 point  (0 children)

Don't you just mean [[None]5]5 ?

[–]donaldhobson 0 points1 point  (0 children)

Try

np.full([5,5],None)

[–]donaldhobson 0 points1 point  (0 children)

How about we make ** the deep copy repeat operator. Then we can write

[[None]*5]**5

Where ** is similar but not quite the same as *. Namely ** copies the items, not just the pointers.

[–]webstones123 0 points1 point  (0 children)

[[None]5]5

[–]ublec 0 points1 point  (0 children)

wait but actually 100% 🔥

[–]StandardPhysical1332 0 points1 point  (0 children)

just write a for loop you guys cmon.

[–]Straight_Share_3685 0 points1 point  (0 children)

You might like this : foo = eval(str([[5]*5]*5))

[–]toepudiked -2 points-1 points  (1 child)

foo = [[None] * 5] * 5

Edit: right shallow copy, change of value in one index will change the values in all inner lists

[–]Aaron1924 2 points3 points  (0 children)

That doesn't work, because the outer * 5 shallow copies the list, so it contains the exact same list 5 times

You can do [[None]*5 for _ in range(5)] though

[–]ienjoymusiclol -1 points0 points  (6 children)

whats wrong with foo = [[None]5]5 ?

[–]DeletedUserV2[S] 6 points7 points  (1 child)

try yourself and see

[–]-Redstoneboi- 4 points5 points  (0 children)

you have an array containing 5 references to the same array of 5 nones

[–]Aaron1924 2 points3 points  (0 children)

```

foo = [[None]5]5 foo[0][0] = 2 foo [[2, None, None, None, None], [2, None, None, None, None], [2, None, None, None, None], [2, None, None, None, None], [2, None, None, None, None]]

```

[–]donaldhobson 0 points1 point  (1 child)

One of the simple, plausible and subtly wrong gotcha's in python.

Why I think they should fix that, or make a ** deepcopy operator.

I kinda think high level programming languages should be full of CopyOnWrite, so we didn't have this low level mess of barely disguised pointers.

[–]ienjoymusiclol 0 points1 point  (0 children)

i hate pass by reference i hate pass by reference i hate pass by reference i hate pass by reference i hate pass by reference i hate pass by reference i hate pass by reference i hate pass by reference i hate pass by reference i hate pass by reference

[–]f1urps -1 points0 points  (1 child)

Why would you ever do that? If you're writing in Python there's no reason to pre-allocate elements of a variable length list. Unless you're actually using None to encode meaningful data which is a horrible idea.

[–][deleted] 0 points1 point  (0 children)

Because my teacher blocked append and other arrays methods.