Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how python interpreter treats the position of the function definition having default parameter

Why the first code outputs 51 and the second code outputs 21. I understand the second code should output 21, but the way I understood, the first code should also output 21 (The value of b changed to 20 and then is calling the function f). What am I missing?

b = 50

def f(a, b=b):
    return a + b

b = 20
print(f(1))

Output: 51

b = 50
b = 20

def f(a, b=b):
    return a + b
print(f(1))

Output: 21

Edit: This is different from How to change default value of optional function parameter in Python 2.7? because here the unintentional change happening to the default parameter is being discussed, not how to intentionally change the value of default parameter, ie here the question focuses on how the python interpreter treats the position of function definition for functions having default parameters.

like image 572
Nandu Raj Avatar asked May 11 '20 06:05

Nandu Raj


3 Answers

Tip for python beginners : If you use IDEs like pycharm - you can put a debugger and see what is happening with the variables.

We can get a better understanding of what is going on using the id(b) which gets us the address of the particular object in memory:

Return the “identity” of an object. This is an integer which is guaranteed to be unique and constant for this object during its lifetime. Two objects with non-overlapping lifetimes may have the same id() value.

CPython implementation detail: This is the address of the object in memory.

Let me modify your code to the following :

b = 50
print("b=50 :", id(b))


def f(a, b=b):
    print("b in the function f :", id(b))
    print(id(b))
    return a + b


b = 20
print("b=20 :", id(b))
print(f(1))

The output is as following:

b=50 : 4528710960
b=20 : 4528710000
b in the function f : 4528710960
4528710960
51

As you can see the b inside the function and the b=50 have the same address.

When you do b=20 a new object was created.

In Python, (almost) everything is an object. What we commonly refer to as "variables" in Python are more properly called names. Likewise, "assignment" is really the binding of a name to an object. Each binding has a scope that defines its visibility, usually the block in which the name originates.

In python

When you do

b=50 a binding of b to an int object is created in the scope of the block

When we later say b=20 the int object b=50 is unaffected. These both are essentially two different objects.

You can read more about it in these links.

  • Is Python call-by-value or call-by-reference? Neither.
  • Parameter Passing
  • Python id()
like image 184
Sanjeev Siva Avatar answered Nov 05 '22 19:11

Sanjeev Siva


Think of how the interpreter treats this. In the first case, def f(a, b=b) is interpreted as def f(a, b=50) since the value of b in the current scope is 50. As such, f(1) assigns a to 1, and thus, a + b = 1 + 50 = 51.

Similarly, in the second case, the value of b in the current scope is 20 when the function is declared, so the definition is interpreted as def f(a, b=20). Therefore, f(1) = 21.

like image 4
A.J. Uppal Avatar answered Nov 05 '22 18:11

A.J. Uppal


The reason why the different placement of the function is resulting in different errors is because of the placement of the value 'b' as well.

Since the function 'f', is using a named parameter 'b', so it takes the first assignment of the variable 'b' as the argument/parameter to the function 'f'

For example,

b = 50

def f(a, b=b):
    return a + b

b = 20
print(f(1))

As you pointed out, this results in the output 51

But if I were to change the code by a bit to

def f(a, b=b):
    return a + b
b = 50
b = 20
print(f(1))

It would result in the following error:

def f(a, b=b):
NameError: name 'b' is not defined

Hence, we can deduce that the placement of the variable which is taken as a named parameter to the function is causing the difference in outputs.

You can also use the global variables for the same.

like image 3
Alen S Thomas Avatar answered Nov 05 '22 19:11

Alen S Thomas