Python Encapsulation Question

Hi there, I've got some experience with writing Java and have decided to attempt to pick up Python via Automatetheboringstuff (which is pretty good I must say).

So in chapter 8 (reading and writing files) there is an exercise to generate a bunch quizzes with randomized order of answers. I'm trying to write my own implementation before comparing it to the given answers. However I've stumbled upon a concept in python that has confused me.

My code is at https://pastebin.com/6sEMMKeT

For some reason, when I iterate through the list of states and remove the correct answer, it seems to remove the capital for the global variable as well. I assumed that when I linked the global variable to a local variable in a for loop, the global should not be affected. But here, I'm seeing a decrease even in the global variable.

Is this normal behaviour or have I missed a major concept in programming?

6 comments · 100% upvoted · other discussions

comments

novice_at_life

When you say wrongAns = capList you're just making a new pointer to the same list. Instead you want to import copy and say wrongAns = Copy.copy(capList) this will give you a copy of the list that you can change without affecting the original.

EndUsersarePITA [OP]

OOOOHHHH.... its a pointer assignation? I did not know that. I thought it would create a new object. How come this does not apply to variables as well? For example :

x = 1
y = x
print(str(y)) #results 1
x = 2
print(str(y)) #results 1
vervain9

When you assign variable a to another variable b, both a and b are pointing to the same object in memory. Lists are also mutable so if you modify the list using either variable, both will be pointing to that modified list (which is what you see in your example).

a = list(range(10))
b = a
id(a) == id(b)
# True
a.pop()
# 9
a == b
# True
b
# [0, 1, 2, 3, 4, 5, 6, 7, 8]

You can get around this by copying the list

focusCap = list(stateList)
EndUsersarePITA [OP]

Thank you for the example. You are absolutely right. But this doesn't apply to variables though.

For example :

x = 1
y = x
print(str(y)) #results 1
x = 2
print(str(y)) #results 1
vervain9

In your original example you have two variables pointing at the same list and you then modify the underlying list that both variables point to using random.shuffle (which changes the order of items in a list without creating a new list).

In this case you're re-assigning x to 2, which is a completely new object, and will not affect y. x and y are not linked, they were just both pointing to the same object originally (the int 1). Once you do x = 2, you're making x point to something else.

AlSweigart

This section on mutable and immutable objects explains why you're seeing this behavior: https://automatetheboringstuff.com/chapter4/#calibre_link-125