Passing an integer by reference in Python

PythonFunctionPass by-ReferencePass by-Value

Python Problem Overview


How can I pass an integer by reference in Python?

I want to modify the value of a variable that I am passing to the function. I have read that everything in Python is pass by value, but there has to be an easy trick. For example, in Java you could pass the reference types of Integer, Long, etc.

  1. How can I pass an integer into a function by reference?
  2. What are the best practices?

Python Solutions


Solution 1 - Python

It doesn't quite work that way in Python. Python passes references to objects. Inside your function you have an object -- You're free to mutate that object (if possible). However, integers are immutable. One workaround is to pass the integer in a container which can be mutated:

def change(x):
    x[0] = 3

x = [1]
change(x)
print x

This is ugly/clumsy at best, but you're not going to do any better in Python. The reason is because in Python, assignment (=) takes whatever object is the result of the right hand side and binds it to whatever is on the left hand side *(or passes it to the appropriate function).

Understanding this, we can see why there is no way to change the value of an immutable object inside a function -- you can't change any of its attributes because it's immutable, and you can't just assign the "variable" a new value because then you're actually creating a new object (which is distinct from the old one) and giving it the name that the old object had in the local namespace.

Usually the workaround is to simply return the object that you want:

def multiply_by_2(x):
    return 2*x

x = 1
x = multiply_by_2(x)

*In the first example case above, 3 actually gets passed to x.__setitem__.

Solution 2 - Python

Most cases where you would need to pass by reference are where you need to return more than one value back to the caller. A "best practice" is to use multiple return values, which is much easier to do in Python than in languages like Java.

Here's a simple example:

def RectToPolar(x, y):
    r = (x ** 2 + y ** 2) ** 0.5
    theta = math.atan2(y, x)
    return r, theta # return 2 things at once

r, theta = RectToPolar(3, 4) # assign 2 things at once

Solution 3 - Python

Not exactly passing a value directly, but using it as if it was passed.

x = 7
def my_method():
    nonlocal x
    x += 1
my_method()
print(x) # 8

Caveats:

  • nonlocal was introduced in python 3
  • If the enclosing scope is the global one, use global instead of nonlocal.

Solution 4 - Python

Really, the best practice is to step back and ask whether you really need to do this. Why do you want to modify the value of a variable that you're passing in to the function?

If you need to do it for a quick hack, the quickest way is to pass a list holding the integer, and stick a [0] around every use of it, as mgilson's answer demonstrates.

If you need to do it for something more significant, write a class that has an int as an attribute, so you can just set it. Of course this forces you to come up with a good name for the class, and for the attribute—if you can't think of anything, go back and read the sentence again a few times, and then use the list.

More generally, if you're trying to port some Java idiom directly to Python, you're doing it wrong. Even when there is something directly corresponding (as with static/@staticmethod), you still don't want to use it in most Python programs just because you'd use it in Java.

Solution 5 - Python

Maybe it's not pythonic way, but you can do this

import ctypes

def incr(a):
    a += 1

x = ctypes.c_int(1) # create c-var
incr(ctypes.ctypes.byref(x)) # passing by ref

Solution 6 - Python

A numpy single-element array is mutable and yet for most purposes, it can be evaluated as if it was a numerical python variable. Therefore, it's a more convenient by-reference number container than a single-element list.

    import numpy as np
    def triple_var_by_ref(x):
        x[0]=x[0]*3
    a=np.array([2])
    triple_var_by_ref(a)
    print(a+1)

output:

7





Solution 7 - Python

In Python, every value is a reference (a pointer to an object), just like non-primitives in Java. Also, like Java, Python only has pass by value. So, semantically, they are pretty much the same.

Since you mention Java in your question, I would like to see how you achieve what you want in Java. If you can show it in Java, I can show you how to do it exactly equivalently in Python.

Solution 8 - Python

Maybe slightly more self-documenting than the list-of-length-1 trick is the old empty type trick:

def inc_i(v):
    v.i += 1

x = type('', (), {})()
x.i = 7
inc_i(x)
print(x.i)

Solution 9 - Python

The correct answer, is to use a class and put the value inside the class, this lets you pass by reference exactly as you desire.

class Thing:
  def __init__(self,a):
    self.a = a
def dosomething(ref)
  ref.a += 1

t = Thing(3)
dosomething(t)
print("T is now",t.a)

Solution 10 - Python

class PassByReference:
	def Change(self, var):
		self.a = var
		print(self.a)
s=PassByReference()
s.Change(5)		

Solution 11 - Python

In Python, everything is passed by value, but if you want to modify some state, you can change the value of an integer inside a list or object that's passed to a method.

Solution 12 - Python

class Obj:
  def __init__(self,a):
    self.value = a
  def sum(self, a):
    self.value += a
    
a = Obj(1)
b = a
a.sum(1)
print(a.value, b.value)// 2 2

Solution 13 - Python

integers are immutable in python and once they are created we cannot change their value by using assignment operator to a variable we are making it to point to some other address not the previous address.

In python a function can return multiple values we can make use of it:

def swap(a,b):
    return b,a

a,b=22,55
a,b=swap(a,b)
print(a,b)

To change the reference a variable is pointing to we can wrap immutable data types(int, long, float, complex, str, bytes, truple, frozenset) inside of mutable data types (bytearray, list, set, dict).

#var is an instance of dictionary type

def change(var,key,new_value):
    var[key]=new_value

var =dict()
var['a']=33
change(var,'a',2625)
print(var['a'])

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionCodeKingPlusPlusView Question on Stackoverflow
Solution 1 - PythonmgilsonView Answer on Stackoverflow
Solution 2 - PythonGabeView Answer on Stackoverflow
Solution 3 - PythonUriView Answer on Stackoverflow
Solution 4 - PythonabarnertView Answer on Stackoverflow
Solution 5 - PythonSergey KovalevView Answer on Stackoverflow
Solution 6 - PythonTrisoloriansunscreenView Answer on Stackoverflow
Solution 7 - PythonnewacctView Answer on Stackoverflow
Solution 8 - PythonmheymanView Answer on Stackoverflow
Solution 9 - PythonChris PugmireView Answer on Stackoverflow
Solution 10 - PythonshrutiView Answer on Stackoverflow
Solution 11 - PythonrecursiveView Answer on Stackoverflow
Solution 12 - PythonJillAndMeView Answer on Stackoverflow
Solution 13 - PythonUdesh RanjanView Answer on Stackoverflow