By CodeKingPlusPlus


2013-03-01 00:45:14 8 Comments

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?

10 comments

@Sergey Kovalev 2019-06-07 14:15:16

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

@Uri 2018-08-19 12:15:37

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.

@Trisoloriansunscreen 2018-02-16 03:52:10

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:

3

@mheyman 2017-04-27 13:50:01

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)

@markrages 2017-11-28 23:36:12

Or wrap the number in a class: github.com/markrages/python_mutable_number

@recursive 2013-03-01 00:46:50

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.

@recursive 2014-10-14 23:49:54

Any downvoters care to comment?

@Astery 2016-04-06 16:04:14

I think, because everything is passed by value is not really true. Quote docs: arguments are passed using call by value (where the value is always an object reference, not the value of the object)

@Mashakal 2017-09-23 15:58:03

Lists, objects, and dictionaries are passed by reference

@recursive 2017-09-23 16:35:45

If that were true, assignment to a parameter in a function would be reflected at the call site. As Astery quoted passing is by value and those values are object references.

@mgilson 2013-03-01 00:50:51

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__.

@user102008 2013-04-08 02:31:33

"Python passes objects." No. Python passes references (pointers to objects).

@mgilson 2013-04-08 12:25:10

@user102008 -- Fair point. The semantics at this point get very muddy I feel. Ultimately, they're not "pointers" either. At least, certainly not in the same sense as you have in C. (They don't have to be dereferenced, for example). In my mental model, it's easier to think of things as "Names" and "Objects". Assignment binds a "Name"(s) on the left to an "Object"(s) on the right. When you call a function, you pass the "Object" (effectively binding it to a new local name within the function).

@mgilson 2013-04-08 12:26:13

This is of course a description of what python references are, but it's not easy to find a way to describe it succinctly to those who aren't familiar with the terminology.

@mgilson 2013-04-08 12:29:48

It's no wonder we get confused with the terminology. Here we have it described as call-by-object and here it is described as pass-by-value. Elsewhere it's called "pass-by-reference" with an asterisk on what that actually means... Basically, the problem is that the community hasn't figured out what to call it

@user102008 2013-04-08 19:00:54

Right and also I would rather not mention "passing" at all, because that is what people are confused about. In Python, every expression evaluates to a reference (i.e. all values are references). When you create an object, you get a reference. When you call a function, it returns a reference. When you access an attribute, the thing on the left is a reference. Basically, it's all references. Anything done to objects must be done through references that point to it. So it's no surprise that when you pass things, they are also references.

@user102008 2013-04-08 19:05:00

Python references are the exact same as Java references. And Java references are according to the JLS pointers to objects. And there is basically a complete bijection between Java/Python references and C++ pointers to objects in semantics, and nothing else describes this semantics as well. "They don't have to be dereferenced" Well, the . operator simply dereferences the left side. Operators can be different in different languages.

@Gabe 2013-03-01 04:21:28

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

@shruti 2014-02-04 06:44:41

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

@newacct 2013-03-01 04:15:41

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.

@abarnert 2013-03-01 00:53:38

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.

@Luis Masuelli 2014-03-30 03:06:06

JAVA doesn't pass integers by reference (integers or any object. boxed objects are replaced as well upon assignment).

@Kroltan 2017-04-27 14:00:51

@LuisMasuelli Well, boxed primitves are treated just like objects, the only thing preventing their use as the OP wants is the fact that boxes are immutable (and since the primitives themselves are also immutable, the whole thing is immutable and can only be changed at variable level)

@z33k 2019-07-29 11:46:02

A good use case for this is counting a number of calls (a total, not depth) inside a recursive function. You need a number that can be incremented in all branched out calls. A standard int just doesn't cut it

Related Questions

Sponsored Content

22 Answered Questions

[SOLVED] Does Python have a ternary conditional operator?

41 Answered Questions

[SOLVED] How to merge two dictionaries in a single expression?

9 Answered Questions

83 Answered Questions

[SOLVED] Is Java "pass-by-reference" or "pass-by-value"?

12 Answered Questions

[SOLVED] Calling a function of a module by using its name (a string)

  • 2008-08-06 03:36:08
  • ricree
  • 608392 View
  • 1500 Score
  • 12 Answer
  • Tags:   python object

31 Answered Questions

[SOLVED] "Least Astonishment" and the Mutable Default Argument

16 Answered Questions

[SOLVED] What are metaclasses in Python?

30 Answered Questions

[SOLVED] Is JavaScript a pass-by-reference or pass-by-value language?

26 Answered Questions

[SOLVED] How do I pass a variable by reference?

34 Answered Questions

[SOLVED] How do I sort a dictionary by value?

Sponsored Content