tags:

views:

55

answers:

3

Hello, given:

foo = "foo"
def bar(foo):
    foo = "bar"

bar(foo)
print foo

# foo is still "foo"...

foo = {'foo':"foo"}
def bar(foo): 
    foo['foo'] = "bar"

bar(foo)
print foo['foo']

# foo['foo'] is now "bar"?

I have a function that has been inadvertently over-writing my function parameters when I pass a dictionary. Is there a clean way to declare my parameters as constant or am I stuck making a copy of the dictionary within the function?

Thanks!

+1  A: 

Arguments are passed by value, but in this case the value is a reference to an object. This is also called call by sharing. So yes, if you need a new dictionary, you will have to create one in the function.

Matthew Flaschen
+2  A: 

In a case like this, you'd have to copy the dictionary if you want to change it and keep the changes local to the function.

The reason is that, when you pass a dictionary into your second bar function, Python only passes a reference to the dictionary. So when you modify it inside the function, you're modifying the same object that exists outside the function. In the first bar function, on the other hand, you assign a different object to the name foo inside the function when you write foo = "bar". When you do that, the name foo inside the function starts to refer to the string "bar" and not to the string "foo". You've changed which object the name refers to. But foo inside the function and foo outside the function are different names, so if you change the object labeled by foo inside the function, you don't affect the name foo outside the function. So they refer to different objects.

David Zaslavsky
Fair enough. I was hoping that there would be something like a const keyword to make this a little nicer.Thanks a lot!
Shaun Meyer
This is a point where I'd make a shameless plug for learning C++. Half of these sort of misunderstandings in high-level languages come from a lack of understanding of how the languages work. If you take the time to learn a bit of C++ you'll start to find that allot of these sort of things in Python are the way they are because they are either a) the fastest or b) the easiest implementation. You don't have to know C++ to understand how Python works, but it makes it easier.
Timothy Baldridge
@Shaun: nothing is really constant in Python (except keyword names like `None`, `True`, `False`, `1`, `2`, etc.) and anyway, a `const` keyword wouldn't help you here because your second `bar()` is performing an operation on the object named `foo`, not changing what the name refers to. `const` prevents the latter but not the former. Timothy has a good point that learning C++ (or C) would probably help make this clearer.
David Zaslavsky
@David, presumably a const foo function parameter would cause an interpreter error on the line where you attempt to modify the content of foo.
jmucchiello
@jmucchiello: the thing is, since Python is so flexible in allowing you to change built-in behavior, it's nearly impossible to tell for certain whether any particular piece of code actually modifies the object or not. For instance, I could create an object `foo` such that the line `foo['foo'] = "bar"` just prints `bar` to the console and doesn't modify `foo`. It would be really weird, but it could be done.
David Zaslavsky
A: 

I would like to add that

temp_dict = CONSTdict 

did not help, as this simply copies the pointer.

Instead, I needed:

temp_dict = dict(CONSTdict)

Cheers,

Shaun

Shaun Meyer