GermainZ
GermainZ

Reputation: 1943

Copying a list in python

I'm looking for a way to do the following:

Thanks a lot!

EDIT: The sublists aren't necessarily named the same (table1, table2, table3). Actually, their names are quite different (e.g. up, down, left, right)

EDIT #2: I'm kinda new to this. Basically, here's my code:

up=["img1.png","img2.png"]

similar things for down, left and right.

table=[up,down,left,right]

Now using pygame:

for j in range(len(table)):
        for i in range(len(table[j])):
            table[j][i] = pygame.image.load(os.path.join(str(table[j][i])))
            table_r[j][i] = pygame.image.load(os.path.join(str(table_r[j][i])))
            table_r[j][i] = pygame.transform.flip(table_r[j][i],1,0)

This wouldn't work as there is no up_r, for example, that I could access. Only up.

Upvotes: 2

Views: 163

Answers (3)

lvc
lvc

Reputation: 35059

On the more general issues raised in the comments and by your edits - it seems very much like a list of lists isn't the right data structure for your logic here. A list is usually indicated when you can have arbitrarily many 'rows' in your table - it seems you always have exactly four. A tuple is better in this case - it is kindof like a list, except it is set up more deliberately for things that don't change. And, even better, since you want to address your four things by name, there's a standard Python class called collections.namedtuple that makes this easy.

You would define a Table class like this:

Table = namedtuple('Table', ['up', 'down', 'left', 'right'])

And then you create your first table like this:

table = Table(up=["img1.png","img2.png"], down=..., left=..., right=...)

This lets you get your 'up' list as table.up, which means when you do a deepcopy into table_r per Constantinius' answer, these names come with it for free. And it also lets you iterate over it in exactly the same way as your list:

for i in range(len(table)):
    for j in range(len(table[i])):
       ...

However, note that iterating over range(len(iterable)) is usually not necessary - since you're using the index to look up values from your two tables simultaneously, what you really want is a combination of the builtin functions enumerate and zip:

for row, row_r in zip(table, table_r):
    for i, (val, val_r) in enumerate(zip(row, row_r)):
       row[i] = pygame.image.load(os.path.join(str(val)))
       row_r[i] = pygame.image.load(os.path.join(str(val_r)))

You only need the index to assign into the lists, since rebinding val and val_r inside the inner loop won't work. Since you don't use j as anything other than a lookup, you don't need it at all.

But this also brings up the one caviat of using a namedtuple - the one thing it can't do that you might care about is change an attribute of the tuple after it is created:

>>> from collections import namedtuple
>>> Point = namedtuple('Point', ['x', 'y'])
>>> p = Point(1, 2)
>>> p.x = 2
Traceback (most recent call last):
  File "<pyshell#3>", line 1, in <module>
    p.x = 2
AttributeError: can't set attribute

In your case, this means you can't reassign table.up to a new list at any point (you can still change the list itself, though, through its mutation methods and slice assignment) - if you need that, you're best off coding your own class for this.

Upvotes: 1

Marco de Wit
Marco de Wit

Reputation: 2804

TABLE_1 = [ table[:] for table in TABLE ]

This only suits your purpose if the tables in TABLE do only contain immutables.

Upvotes: 1

Constantinius
Constantinius

Reputation: 35039

I think, the deepcopy function suits fine in this occasion.

from copy import deepcopy

...
TABLE_1 = deepcopy(TABLE)

Upvotes: 8

Related Questions