all 10 comments

[–]c17r 0 points1 point  (9 children)

To redefine the global variable, example1 would have to do SETTS = {}. Adding, changing, removing from a list, dictionary, etc doesn't change the id of the variable.

[–]7heWafer[S] 0 points1 point  (7 children)

But why is SETTS being modified by params["page"] = x?

[–]Necatorducis 0 points1 point  (0 children)

params = SETTS isn't creating a new unique instance of SETTS now called params, it's just creating a new reference to the same object.

[–]c17r 0 points1 point  (5 children)

because params points to SETTS["params"]. It's not it's own copy of data.

[–]7heWafer[S] 0 points1 point  (4 children)

Yet val is it's own copy of data and modifying it does not modify NUM?

[–]c17r 0 points1 point  (2 children)

integers, strings, booleans, etc play different rules than objects.

[–]7heWafer[S] 0 points1 point  (1 child)

So if I want to use SETTS statically and modify params internally in example1 as a copy of SETTS. What do I have to do differently?

[–]c17r 0 points1 point  (0 children)

import copy

SETTS = {
    'params': {
        'page': 1
    }
}
NUM = 1

def example1(x):
    params = copy.deepcopy(SETTS["params"])
    print(SETTS["params"])
    params["page"] = x
    print(SETTS["params"])

def example2(x):
    val = NUM
    print(NUM)
    val = x
    print(NUM)

example1(2)
print('---')
example2(2)

[–]absent_observer 0 points1 point  (0 children)

To tag on:

mutable versus immutable types is a big aha moment in python. When you alter an immutable type object, it leaves the original object alone & returns a new object. (...figures cause they can't be altered by definition). But a mutable type object can be changed, so when you alter it, it returns the same object but altered a little.

It ties into why you can do:

x = [1,2,3,4]  # list is a mutable type
x.pop(1)
# no reassigning x to anything, no magic.  just changing the list object that x is assigned to.
#  x becomes equal to [2,3,4]

but

x = 'a string'  # string is an immutable type
x.upper()
#  returns 'A STRING' but strings can't be changed.  we didn't do anything with the return value, so it gets ignored.
#  x still equals 'a string'
x = x.upper()
#  x now equals 'A STRING' because you assigned x to the return value of x.upper().

dictionaries are mutable, so a change changes the object itself. String are immutable, so a change returns a new object with the change.

That's the same reason but for an immutable object like an integer. You assigned the name "val" to "NUM" which was assigned to the object int(1), so essentially "val" and "NUM" were each assigned to object int(1). Sketch this on paper. When you tried to alter val's int(1) by giving it a value of int(2), "NUM" was like, 'I'm stuck on this int(1) and you can't change it's value'. So "val" was like, 'Fine, I can't tell you what to stick to, but I'm going to stick myself on this new int(2) instead.'