3

i'm learning python and hit a wall. I am trying to define a 2d list which i can later use to append values. This corresponding to a grid of width *height

I tried using [] to initialize the empty lists but then the wid is ignored. I tried using None as a placeholder but then i can't append

wid = 3
hgt = 3
l1 = [[]*wid ] * hgt
l = [[None]*wid ] * hgt
l[1][1].append("something")

Result

l1: [[], [], []]

l: [[None, None, None], [None, None, None], [None, None, None]]

Error:

append: AttributeError: 'NoneType' object has no attribute 'append'

desired result: [[[], [], []], [[], [], []], [[], [], []]]

2

4 Answers 4

7

Try using a list comprehension within a list comprehension:

>>> [ [ [] for i in range(wid) ] for i in range(hgt) ]
[[[], [], []], [[], [], []], [[], [], []]]

Note this is preferred to list multiplication because each of these lists is unique. Compare:

>>> x = [ [[] for i in range(wid)] for i in range(hgt) ]
>>> x[1][1].append('a')
>>> x
[[[], [], []], [[], ['a'], []], [[], [], []]]

vs.

>>> y = [ [[]] * wid for i in range(hgt) ]
>>> y[1][1].append('a')
>>> y
[[[], [], []], [['a'], ['a'], ['a']], [[], [], []]]

vs.

>>> z = [ [[]] * wid ] * hgt
>>> z[1][1].append('a')
>>> z
[[['a'], ['a'], ['a']], [['a'], ['a'], ['a']], [['a'], ['a'], ['a']]]

Where, in the second and third cases, 'a' appears in multiple cells! And using None does not avoid this problem:

>>> m = [ [None] * wid ] * hgt
>>> m
[[None, None, None], [None, None, None], [None, None, None]]
>>> if m[1][1] is None:
...     m[1][1] = ['a']
... else:
...     m[1][1].append('a')
...
>>> m
[[None, ['a'], None], [None, ['a'], None], [None, ['a'], None]]

tl;dr - use the double list comprehension. In my opinion, it's the most readable option anyway.

Sign up to request clarification or add additional context in comments.

3 Comments

And refer to this guy! List comprehension is considerably important in Python and I highly recommend you to search a little more about it :)
This answers only part of the question (OP might still try to append to those None entries)
Thanks for your solution and explenation! exactly what i wanted to know.
2

There's two ways to do it

  1. use None as placeholder value, and replace it with l[1][1] = 5
  2. use empty lists and append new elements to them, with l[1].append(5)

Currently, you are mixing the two ways. the l[1][1] returns a None value, not a list, and you are trying to call append on it.

Regardless, there is a common python trap here. When you write

mylist = [[None]*2]*3

this does two things

  1. creates a list [None, None]
  2. uses this list 3 times to create another list

The key is that the outer list will consist of 3 copies of the inner list, not of 3 different by identical lists. so, everytime you modify one of them, the rest will be modified too. So, you need to make copies of the inner list.

For a 2D array however, the best way would be to use numpy

x = np.zeros(m, n)
x[1, 2] = 5

4 Comments

This answers only part of the question (the sublists are still all the same instance)
@tobias_k: correct. the question was badly formatted when I read it. editing answer
Thanks for the help! I still get confused sometimes when python copies or references to the same object. This helps a lot! Would performace wise numpy be faster then lists?
@Jop: yes, definitely better performance. but, if you care about performance, you should do matrix operations, avoid for loops
0
>>> x = 5
>>> y = 5
>>> [[None for _ in range(x)] for _ in range(y)]
[[None, None, None, None, None], [None, None, None, None, None], [None, None, None, None, None], [None, None, None, None, None], [None, None, None, None, None]]

Don't use [[None]*x]*y unless you really know that you just created shared references.

Comments

0

if you are dealing with matrices you can use numpy:

import numpy as np

my_matrix = np.zeros((rows, columns) # with 2 dimentions

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.