-2

In Python, the following code prints '0', not '1'.

def inc(x):
    x = x+1

a = 0
inc(a)
print(a)

I understand why this happens; it's because integers are immutable. What I don't understand is how to get around this behaviour when it's undesirable. Suppose we want to create a new command such that the code

a = 0
inc(a)
print(a)

prints '1'.

Obviously, the naive approach won't do it. What can we do instead?

goblin GONE
  • 540
  • 3
  • 12
  • "Suppose we want to create a new command that mutates some integers, or strings, etc., in some kind of pre-specified way" - that would completely defeat all benefit of immutability. – user2357112 Sep 02 '17 at 05:08
  • Like most (all?) programming languages, when you call a function `f(a)` it is impossible for the function to change the object that `a` is bound to. If `a` is a container object its internal state may change, but it will still be the same container when the function returns. Trust me on this: you wouldn't want it any other way. – Paul Cornelius Sep 02 '17 at 05:10
  • @user2357112, have a read of the edited question. Do you still object that this would defeat the benefit of immutability, even with the way I've rephrased it? – goblin GONE Sep 02 '17 at 05:11
  • No, that capability wouldn't interfere with immutability. It's still not something you can do in Python, though. No passing variables by reference here. – user2357112 Sep 02 '17 at 05:14
  • @PaulCornelius, sorry, but I don't trust you. No offense. I mean, I trust you as a human. But I don't trust you to do my thinking for me. Of course, this is a good thing, and the world would be a great deal better if more people were like me in this respect :) – goblin GONE Sep 02 '17 at 05:15
  • If languages worked the way you suggest, every value would have to be passed as a pointer (in C terminology). Every access to such a value would involve de-referencing a pointer. The vast majority of times, the immutability of function arguments is highly desirable; in cases where it isn't you can simply assign the result to the same variable name, like `a = inc(a)` (to borrow from your example). I don't mind that because I get paid by the keystroke anyway (doesn't everybody?) – Paul Cornelius Sep 02 '17 at 05:39
  • @PaulCornelius, I don't think that's a very strong argument. If the built-in assignment command already does certain things, then I'd expect a well-thought out programming language to allow me to create custom commands that also do these kinds of things. I don't know what 'de-referencing' means; I've been studying computer science for about six weeks only. But, whatever it is you're objecting to, it surely applies equally well to the assignment operator. Ergo, if this were a strong objection against doing the kind of thing I'm asking for... – goblin GONE Sep 02 '17 at 05:52
  • ... then it would be an equally strong argument against assignment operators applied in connection immutable types in general. Essentially, you're arguing that `x = x+1` should always be avoided. Well, we can certainly run off and do pure-functional programming, but Python isn't really meant to be used this way. – goblin GONE Sep 02 '17 at 05:55
  • The argument to a function doesn't have to be a single variable; it can be an expression. In that case the calling program would have no variable for the function to modify. For example: `b= 1; a=2; inc(a+b)`. Perfectly legal and quite useful. What would you like to happen in your scheme in such a case? – Paul Cornelius Sep 02 '17 at 06:24
  • @PaulCornelius, well, if we write `a+b = a+b+1` we will get a syntax error. Similarly, I think that `inc(a+b)` should produce an error, or throw some kind of exception. – goblin GONE Sep 02 '17 at 06:29

3 Answers3

0

Similar (a bit more general) question can be found here along with a discussion how Python passes params to functions. In short, without making x variable in your code an object, I believe there's nothing we can do. Of course, you can alter your code to e.g. return changed value from function inc() and print that (i.e. print(inc(x))) or just do the printing from inside the inc() method, but that's not what you're essentially looking for.

0

If I understand correctly, You are trying to increment variable a using function inc(var) and passing 'a' as a external variable to the function inc().

As @Marko Andrijevic stated, variable x passed to function inc() and variable x defined in the function are different . One way to achieve is by returning value of x and collecting externally, which you may not be looking for.

Alternately, Since you have defined variable 'a' outside function ,it can be called global variable. If you want to pass that to a function, and manipulate it, you need to define that variable ('a' in your case) inside the function as global. Something like below.

def inc(x):
    global a
    a = x+1

Now when the new value assigned to 'a' after 'x+1', it is retained after execution of 'inc(x)'

>>> a = 0
>>> inc(a)
>>> a
1

EDIT -1
As per comments by @DYZ . Its correct. declaring global a inside inc() function will always increment a. A better alternative will be , in that case, to return x inside inc() and assign that value to any external variable.
Not an elegant solution, but works as intended.

def inc(x):
    return x+1

Result

>>> a
0
>>> a = inc(a)
>>> a
1
>>> a = inc(a)
>>> a
2
>>> b = 0
>>> b = inc(b)
>>> b
1
>>> a
2
>>> 
Anil_M
  • 10,893
  • 6
  • 47
  • 74
  • 1
    This function is horrible. It pretends to increment its parameter (whatever it is), but instead always silently increments `a`. – DYZ Sep 02 '17 at 05:35
  • @DYZ, I think 'horrible' is a bit of a strong word. Anil_M is just trying to illustrate that technically, the constraints on what I want my new command to do don't pin down it's intended behaviour sufficiently accurately. – goblin GONE Sep 02 '17 at 05:42
0

one can use yield to get variable values.

def inc(x,y,z):
    x += 1
    y+=1
    z+=1
    yield x,y,z          #inc doesn't stop
    yield x+y+z

a=b=c=0
gen=inc(a,b,c)
gen=list(gen)
a,b,c,sum=gen[0]+(gen[1],)     #however, index must still be known
print a,b,c,sum
akp
  • 619
  • 5
  • 12