This link explains the variable assignment very well. https://nedbatchelder.com/text/names.html:
Fact: Python passes function arguments by assigning to them.
For example :
def fn(a):
pass
x = 10
When we say fn(x), it's going to be a = x. Another rule is the arguments are evaluated from left to right.
After saying those two rules, let me re-write the print function in a specific way that matches to our example:
def print_(var1, var2, var3, var4, var5, sep=' ', end='\n'):
sys.stdout.write(str(var1) + sep)
sys.stdout.write(str(var2) + sep)
sys.stdout.write(str(var3) + sep)
sys.stdout.write(str(var4) + sep)
sys.stdout.write(str(var5) + sep)
sys.stdout.write(end)
print_(x, y, fun(), x, y)
Python holds the value of the global x inside the local variable var1.
var1 = x # `x` is 3 now
After the fun() function executes, the x in global changes to 6, but the point is var1 is still 3 not 6:
var1 = x = 3
x = 6
print(var1) # 3
...and print_ is going to use it's local variables (var1 not x).
But from now on whenever Python sees the x, it stores 6 instead. so var4 is 6.
var4 = x # `x` is 6 now
But since the y is a list and you mutated the list, both var2 and y are seeing the change ! Because they both point to the same object:
var2 = y = [3]
y.append(6)
print(var2) # [3, 6]