0

Variables in python are effectively pointers in practical use. The assignment operator “=” automatically creates an effective pointer - unless it is a basic type (called an immutable). Examples of basic data types include: int, float, str and bool. Assignment of these data types do not use pointers .

On the other hand, pointers are used when assigning: lists, dicts, class objects etc.

This is frustrating when I need to assign variables of the latter type (list for example) by value.

For example:

background = [1, 1, 0, 2, 2]
screen = background

background[2] = 8

print(background)  # [1, 1, 8, 2, 2]
print(screen)      # [1, 1, 8, 2, 2]

# However, I did NOT want screen to change

Can this be done?

IqbalHamid
  • 2,324
  • 1
  • 18
  • 24
  • In this simple case you can make a shallow copy of the list like `screen = background[:]`, for more complex types you should look at https://docs.python.org/3/library/copy.html – Chris Doyle Jun 20 '21 at 23:26
  • 1
    Does this answer your question? [List changes unexpectedly after assignment. Why is this and how can I prevent it?](https://stackoverflow.com/questions/2612802/list-changes-unexpectedly-after-assignment-why-is-this-and-how-can-i-prevent-it) – j1-lee Jun 20 '21 at 23:28

2 Answers2

3

Sure, you just need to make a copy. The copy module provides both shallow and deep copies.

import copy

...

screen = copy.copy(background)

A shallow copy (as above) only copies the outermost data structure. In your case, that suffices, since all of the elements of the list are immutable values. If you had nested lists or a more complex data structure, you could use copy.deepcopy to copy the entire structure. Use the latter with caution, as any loops in the structure will cause infinite recursion.

Also, in the case of lists specifically, we can use Python's slice syntax to do a shallow copy even more easily.

screen = background[:]

The a:b slice syntax selects a sublist of a list and always copies. Omitting the beginning index defaults to 0, and omitting the end index defaults to the end of the list, so omitting both copies the whole list.

Silvio Mayolo
  • 62,821
  • 6
  • 74
  • 116
2

There are other ways to assign by value. For example, you can use a list comprehension:

screen = [i for i in background]

This creates a new variable that contains values of background.

There are multiple ways to do this kind of assignment. Another one is using list unpacking:

screen = [*background]

This will unpack variables from the original object and put them into a new list.

Another way is to use copy as suggested in other answer.

NotAName
  • 3,821
  • 2
  • 29
  • 44