13

I'd like to implement a function that allows the values of its arguments to be reallocated 'in place'.

As an example, a function that will increment argument x and decrement argument y. (This is just a simple example for illustration - the motivation is that X and Y are in fact single elements of a large dataframe; their expressions are unwieldy; and this operation will undergo many iterations.)

def incdec(x,y,d):
    x += d
    y -= d

Ideally this would be run as:

X = 5; Y = 7; d = 2
incdec(X,Y,d)

to find that the values are now X = 7 and Y = 5. But of course it doesn't work like that - I wondered why?

Andrew Barber
  • 39,603
  • 20
  • 94
  • 123
user2383521
  • 323
  • 1
  • 4
  • 10
  • 1
    You cannot rebind such variables in a function, no. – Martijn Pieters Mar 11 '14 at 23:14
  • This is impossible for your given example as a function has no way of rebinding the variables passed to it. You can of course still change references inside of any object passed to your function, thus it might be possible to work something out for your actual use case if you describe it in more detail. – l4mpi Mar 11 '14 at 23:26
  • If you had, say, lists as inputs this should work (i.e. `def incedec(x,y,d): x[0] += d; x[0] += d;` where `X=[5]; Y=[7]`. It's all about mutable and immutable data types. – Aleksander Lidtke Mar 11 '14 at 23:33
  • 1
    There are at least two workarounds for what you try to implement; wrote a short gist as answer: https://gist.github.com/miku/9497430 – miku Mar 11 '14 at 23:38
  • If you truly have a dataframe or numpy array, yes. variables as you show them, no. If you can you update your question to be numpy, that would help. – Phil Cooper Mar 11 '14 at 23:41
  • I know this has been a while, but I've reopened re: @PhilCooper's comment, and edited your question to try to emphasize you are talking about dataframes. The behavior there can be different than that of strings, as the previously marked duplicate was about. – Andrew Barber Apr 11 '14 at 15:20
  • I think there is two issue: one is variable rebinding in function; one is the type of variable. The only possible combination is passing mutable variable (list, dict) to function without rebinding it. – Jerry Meng Apr 11 '14 at 16:10

1 Answers1

4

Why does your function not change the final values of X and Y ?

In Python When a function with arguments is called, copies of the values of the arguments are stored in local variables. Indeed when you write

def incdec(x,y,d):
    x += d
    y -= d

the only thing that changes are the x and y that are IN THE function indec. But at the end of the function local variables are lost. To obtain what you want you should remember what the function did. To remember those values AFTER the function you should re-assigne x and y like this:

def incdec(x,y,d):
    x += d
    y -= d
    return (x,y)

# and then 

X = 5; Y = 7; d = 2
X,Y = incdec(X,Y,d)

this works because X,Y are of type int. What you also could do is using a list to have a direct access to the variables you want to change.

def incdec(list_1,d):
    list_1[0] += d
    list_1[1] -= d
    #no return needed

# and then 
X = 5; Y = 7; d = 2
new_list = [X, Y]
incdec(new_list,d) #the list has changed but not X and Y

Don t get me wrong, the arguments passed are still a copy as I said earlier but when you copy a list, only references are copied, but those are still looking at the same object. Here's a demo:

number = 5
list_a = [number] #we copy the value of number
print (list_a[0]) # output is 5
list_b = list_a # we copy all references os list_a into list_b
print(list_b[0]) # output is 5
list_a[0]=99
print(list_b[0]) # output is 99
print(number)    # output is 5

as you can see list_a[0] and list_b[0] is one same object but number is a different one That s because we copied the value of number and not the reference. I recommend you to use the first solution. I hope this helped.

Walle Cyril
  • 3,087
  • 4
  • 23
  • 55
  • 1
    In case of dictionary too, no return is needed. They are passed by reference in function (https://stackoverflow.com/a/15078615/4594227). – shaurya airi Mar 17 '20 at 15:19