0

In the following code, I pass a reference to a class variable, using its class name, to a method in another class, expecting it to modify it, but it doesn't. As I understand it, Python always passes parameters by reference, never by value, so I would expect the class variable value to have changed. Why not?

Python 3.6.7 (v3.6.7:6ec5cf24b7, Oct 20 2018, 12:45:02) [MSC v.1900 32 bit (Intel)] on win32
>>> class Other:
...     def modify(self, another_class_member):
...         another_class_member += 1
...         
>>> class Mine:
...     cls_incrementer = 0
...     def __init__(self):
...         self.my_other = Other()
...         
>>> mine = Mine()
>>> mine.cls_incrementer
0
>>> mine.my_other.modify(Mine.cls_incrementer)
>>> Mine.cls_incrementer
0
>>> mine.cls_incrementer
0
David Wallace
  • 212
  • 4
  • 12
  • The assignment *in* `.modify()` creates a new name/variable whose scope is only valid *within* the method. The right-hand-side of the assignment uses the value of the argument passed in but the name on the left-hand-side of the assignment is only withing the scope of the method. Was that confusing? – wwii Apr 23 '19 at 14:05
  • Thanks for the answers. I can see now that the problem is that I am passing an immutable object via a parameter. The fact that I am trying to modify it via a method in another class is actually irrelevant. – David Wallace Apr 25 '19 at 17:15

2 Answers2

1

This statement creates a local variable and just increments that

another_class_member += 1

If we unpack that we get

another_class_member = another_class_member + 1

Now it should be clear that you are creating a new local variable that shadows your parameter.

Mihai Andrei
  • 1,024
  • 8
  • 11
1

You can't do the way you want, but you can try following:

Python 3.5.2 (default, Nov 12 2018, 13:43:14) 
[GCC 5.4.0 20160609] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> class Other:
...     def modify(self, another_class):
...             another_class.increment()
... 
>>> class Mine:
...     cls_incrementer = 0
...     def __init__(self):
...             self.my_other = Other()
...     def increment(self):
...             self.cls_incrementer += 1
... 
>>> mine = Mine()
>>> mine.cls_incrementer
0
>>> mine.my_other.modify(mine)
>>> mine.cls_incrementer
1
spirit
  • 3,265
  • 2
  • 14
  • 29