Q: Does Python use Pass By Value or Pass By Reference in function calls? A: Technically the correct answer is 'pass by value', but that only tells you a part of the story and is likely to lead to considerable confusion if you take it at face value. If you are coming from a background where this question is meaningful, then you are used to thinking about identifiers in programs pointing to 'variables' (memory locations) in the computer's memory at runtime, and those 'variables' either contain values themselves, or contain pointers to values stored elsewhere in memory. Coming from that background, the things you need to know to understand Python's function call (and assignment!) semantics are as follows: 1) *Every* value in Python is an object 2) *Every* 'variable' in Python is a pointer-to-object 3) Function calls are pass-by-value, where the value being passed is the *pointer* to the object referred to by the variable 4) Return values from functions are *also* pass-by-value where the value being passed on return is a pointer to the object being returned Because this describes the semantics of both function calls and assignments, we call this 'pass by assignment'. Since it effectively passes the objects around, it is also sometimes called 'pass by object'. This, however, is not the most useful way to think about Python semantics. Instead, try thinking in terms of 'namespaces'. Conceptually, a namespace is a mapping from names to objects. Python is rife with namespaces. In the case of a function call, we have the namespace of the caller, and the namespace of the function. When a function call is made, an argument expression is evaluated, yielding an object. (In the case of a single identifier, that is done by simply looking the identifier up in the caller's namespace.) The function's namespace is then constructed, and a mapping is made from the formal parameter name to the _same_ object that resulted from the argument expression evaluation. On function return, the return expression is evaluated, yielding an object. If the calling function assigns the function return result to a name, then in the caller's namespace a mapping is made from that name to the object that resulted from evaluating the return expression. To illustrate, we'll consider a function that takes two arguments. The first argument can be anything, but the second needs to be something that can be indexed by integers and have at least two elements, because we are going to update the second element: >>> def func(a, b): ... a = 7 ... b[1] = 7 Suppose we call this function with two lists: >>> x = [1, 2] >>> y = [3, 4] >>> func(x, y) When func is called, 'a' becomes a mapping in 'func's local namespace to the same list that 'x' points to, while 'b' becomes a mapping to the same list that 'y' points to. After the above call, the values of x and y in the calling program are as follows: >>> x [1, 2] >>> y [3, 7] The first assignment statement in the 'func' changed the *mapping* of 'a' in its local namespace to point to a new object, '7'. This did not affect the mapping of 'x' to the original list in the *caller's* name space. The second assignment changed the second element of the list that is mapped to by 'b' in the 'func's namespace. The list mapped to by 'b' is *the same list* that 'y' maps to in the caller's namespace. Thus when we check the value of 'y' in the caller, we see the updated value of the list. The difference is that the first assignment changes the (local) *mapping* and the second assignment changes (mutates) the *object*.