Ask Your Question

Revision history [back]

click to hide/show revision 1
initial version

Hello, @Bob67846! This is not a bug at all. This is the normal behavior of Python that is inherited by Sage. In Python, arguments are passed by value. Let me explain. This is a quite technical explanation, so I hope not to confuse you.

In order to understand better, let me alter your definition of bla a little bit:

x = 1
def bla(y):
    y = 2
print(x)

When you call something like bla(x), you are passing x by value, meaning that the value of the variable x (which is 1) is "copied into" the variable y (in formal terms, you are creating an object called y, which references the value 1). Then, you reassign y to reference an object with the value 2, but you haven't changed the actual value of x.

Now, with that in mind, let's define bla as you did:

x = 1
def bla(x):
    x = 2
print(x)

In this case, the value of x (which is 1) is copied to a new variable coincidentally called x, too, but which is a totally different object from your external x. The "internal" x is then assigned the value 2, but that doesn't alter your other x. When the function bla ends, the internal x is out of scope, and the external one is back to scope.

This is a quite different behavior from some languages, like C++, Fortran, etc., that allow you to pass by reference. If that were the case, the variable x would change its value to 2. Indeed, if bla passed arguments by reference, then y would be not a copy of the value 1, but a reference to the address in computer memory where the 1 is store. So, when you say y=2, you are saying "change the value stored in that address". In that case, x, which is still pointing to the same address, would show 2 as its value, too. This explanation is also valid with the internal/external x variables.

Now, why does bla2 actually changes the value of a list like L? The thing about lists in Python is that their values are a reference to the memory where they are stored. That is, when you execute

x = 1
L = [1, 2, 3]

the name x references the value 1, but the name L references the address in memory where the list [1, 2, 3] is created. When you call bla2(L), as with any function call in Python, you are passing the value of L (a memory address) to the variable K. As your bla2 modifies K, then it is storing the new value in the same memory address, which is also referenced by L. So L also changes.

In computational jargon, x = 1 is immutable and L = [1, 2, 3] is mutable. And knowing which types of objects are mutable or immutable is very important while programming.

The following image explains better the pass by reference vs. pass by value problem. (I always knew I would find it a use!)

Pass by reference vs. pass by value with cups of coffee