mulllhausen
mulllhausen

Reputation: 4435

inconsistent variable scope in python

it seems that strings and dicts behave fundamentally differently in python. when i pass a string to a function it gets modified in the local function's scope only, but when i do the same with a dict, it gets modified in the scope beyond the function:

def change_str(s):
    s += " qwe"

def change_arr(a):
    a[1] = "qwe"

ss = "asd"
change_str(ss)
print ss
# prints:
# asd

aa = {0:"asd"}
change_arr(aa)
print aa
# prints:
# {0: 'asd', 1: 'qwe'}

is this behavior intentional, and if so then why?

Upvotes: 1

Views: 213

Answers (3)

Joel Cornett
Joel Cornett

Reputation: 24788

Don't let the 'assignment' operator fool you. This is what is really going on in each of these functions:

def change_str(s):
    # operation has been split into 2 steps for clarity
    t = s.__iadd__("qwe") # creates a new string object
    s = t # as you know, without the `global` keyword, this `s` is local.

def change_arr(a):
    a.__setitem__(1, "qwe")

As you can see, only one of these functions actually has an assignment operation. The []= is shorthand for (or equivalent to) .__setitem__().

Upvotes: 1

BrenBarn
BrenBarn

Reputation: 251353

Yes, it's intentional. Each type determines how operators work on it. The dict type is set up so that a[1] = "qwe" modifies the dict object. Such changes will be seen in any piece of code that references that object. The string type is set up so that s += "qwe" does not modify the object, but returns a new object. So other code that was referencing the original object will see no changes.

The shorthand way of saying that is that strings are immutable and dicts are mutable. However, it's worth noting that "dicts are mutable" isn't the whole reason why the behavior happens. The reason is that item assignment (someDict[item] = val) is an operation that actaully mutates a dict.

Upvotes: 1

msvalkon
msvalkon

Reputation: 12077

It is intentional behavior. Strings are immutable in python, so essentially all string operations return a new string and as your functions do not return anything, you cannot see the new string asd qwe. You can change the contents of mutable containers outside of local scope without declaring them global.

You can read more about mutable types in the official documentation of pythons data model.

Upvotes: 5

Related Questions