1

Sorry if the title is not accurate, not sure how to name it properly. the question is. If I do this code:

num = 1

def test_func2(arg):
    arg = 10

test_func2(num)
print(num)

The num will obviously stay 1 But if I do similar thing with objects

class TestClass:

    def __init__(self):
        self.one = 1
        self.two = 2


test_obj = TestClass()


def test_func(arg):
    arg.one = 10

test_func(test_obj)
print(test_obj.one)

The value of test_obj.one will change to 10. Why are integers passed by value and user defined objects by reference?

machazthegamer
  • 593
  • 8
  • 18
user3751086
  • 229
  • 1
  • 3
  • 9

2 Answers2

2

In the first case, num refers to the integer object of value 1. Passing it to a function assigns arg to also refer to the same integer object of value 1, but then arg is reassigned to a new integer object of value 10. num is still referring to the original integer object of value 1.

In the second case, test_obj as assigned the value of a new TestClass instance. Passing it to a function assigns arg to the same TestClass instance. The object itself is altered, and both arg and test_obj still refer to the same object, so even after the function returns, test_obj "sees" the change.

Mark Tolonen
  • 166,664
  • 26
  • 169
  • 251
  • Yeah, I realize that but the question is why does it work differently for a 'regular' variable and the object instance? Which section of documentation should I read to get more info on this? – user3751086 Dec 26 '18 at 08:45
  • @user3751086 It does't work differently. Arguments are just new names for the same objects passed to the function, always. In the first case, the 'arg' was reassigned to a new object. In the second case the original object was modified and `arg` still refers to the original object passed in. – Mark Tolonen Dec 26 '18 at 08:49
  • so that means they work differently, or at lease how I understand that. Exploring the link provided above I now assume tat this behavior difference might be related to mutability of an object instance and immutability of integer. Is this correct? If yes, it explains – user3751086 Dec 26 '18 at 08:58
  • @user3751086 Parameter passing works the same in both cases. What you did in the function was different. You can’t mutate an immutable object, but in the second function if you’d reassigned `arg` instead of mutating its object like the first function you wouldn’t see the object change outside the function. – Mark Tolonen Dec 26 '18 at 16:06
0

This happens because -

  1. In first case, after passing a variable to a function test_func2(num), that value like will be caught in a local variable arg, whose scope is local to the function. After we return from function that variable is destroyed as the function has ended its execution.

    num = 1
    
    def test_func2(arg): // arg catches value 1 here
       arg = 10 // arg variable changed to 10 but this value is not reflected back to num variable
               // so num is still 1
    
    test_func2(num) // function called with variable
    print(num) // that's why 1 gets printed here
    
  2. And when you pass object to the function test_func(test_obj), the arg in function will be a reference to the object it catches i.e., test_obj. That means after modifying arg.one = 10 you are actually modifying the original objects value i.e., test_obj.one = 10.

    def test_func(arg): // arg points to test_obj
      arg.one = 10 // actually changing test_obj.one
    
    test_func(test_obj) // function called with object
    print(test_obj.one) //that's why 10 gets printed here
    
Mithilesh Tipkari
  • 697
  • 1
  • 10
  • 16