-1

Basically, my question is if I pass an argument to a function in Python, assign some other value to it, and then change that value, will both values change or just one? How exactly are function arguments passed in python?

In other words, say I had some class A defined as follows:

class A(object):

    def __init__(self, b):
       self._b = b

class B(object):

    def increment():
       # Do something

    ...

where class B is some class (exactly what it is doesn't really matter) and both b and _b are of type B. If I did the following:

instanceOfB = B()
instanceOfA = A(instanceOfB)
instanceOfA._b.increment()

would instanceOfB change, or would it remain the same?

I hope this question is clear. I am having a lot of trouble explaining what I want to ask, so feel free to ask for clarification!

  • Depends. If what you're passing is a reference, say to a list, then mutating any copy of that reference will impact all of them. If it's an immutible object, say a string or an integer or a tuple, all copies are independent. Which is to say that this doesn't really have anything to do with function calls; you'd have the exact same behavior with assignments. – Charles Duffy Jun 27 '16 at 22:17
  • ...that is: if `a=; b=a; b++` (or `b.append("foo")`, or whatever) mutates `a` for your value ``, then the same behavior will happen with that mutation behind a function call as behind an assignment. The function call has nothing to do with it. – Charles Duffy Jun 27 '16 at 22:19
  • Both `instanceOfB` and `instanceOfA._b` **point** to the same **object**, if that object changes then all pointers will reflect that change, however if one variable is assigned to a different value (like `instanceOfB = 4`) this will not affect the other pointers. – Tadhg McDonald-Jensen Jun 27 '16 at 22:26

1 Answers1

2

You are mangling several things here. The function parameters in your example are never modified. Only the objects to which names and parameters refer are.

Python uses names, which are similar to pointers and references - a name refers to an object, but isn't the object itself. Here, you are binding an instance of B (the object) to instanceOfB (the name):

instanceOfB = B()

If you make an assignment of name to name, the reference behind the name is effectively copied. You have two names independently referring to the same object. If you reassign one name to something else, the other doesn't change.

If you call a function, the name is passed by value. That is, inside the function you have a new name (which may be called the same) that refers to the same object.

instanceOfA = A(instanceOfB)
# -> A.__init__(self=instanceOfA, b=instanceOfB)
# -> instanceOfA._b = instanceOfB

Now, up until this point you have only assigned names. Each assignment creates a copy of the reference, meaning each name works independently. However, there is still just one instanceOfB even though it has multiple names. Both instanceOfA._b and instanceOfB point to the same object.

Now, if you modify the object, you will see this change on every name - since they all just refer back to that same object.

MisterMiyagi
  • 44,374
  • 10
  • 104
  • 119