vmonteco
vmonteco

Reputation: 15423

Method to replace assignation into functions

I know it's not possible to assign a new value to a variable passed as a parameter to a function.

>>> a = 1
>>> def foo(bar):
...     bar = 2
...
>>> foo(a)
>>> a
1

But it is possible to modify it with methods.

>>> a = [1, 2]
>>> def foo(bar):
...     bar.append(3)
...
>>> foo(a)
>>> a
[1, 2, 3]

But is there a method to replace assignation (giving the variable a whole new value). Something to make my first example work :

>>> a = 1
>>> def foo(bar):
...     bar.assign(2)
...
>>> foo(a)
>>> a
2

The only alternatives I found are global variables and designing my own classes.

So my questions are :

  1. Is there such method? (or alternative?)

  2. If there isn't, I must be more a design choice than a oversight. Why this choice? If there are methods to modify a part of the value/content, why not a method to replace/give a whole new value/content?

Upvotes: 2

Views: 163

Answers (4)

user6258347
user6258347

Reputation:

Everything in python is an object, and objects in python are mutable, except when they are not. Basic types like strings, numbers (int, float) are not mutable ie. 1 is always 1, and you can never make 1 something else.

This is actually the case with most so called object oriented languages and is more of an optimization.

As you said, you would need to create your own Object that wraps the immutable types in order to mutate the internals of your new object. You can even create a very simple class to do this

class Mutatable:
    def __init__(self, value):
        self.value = value
    def assign(self, value):
        # in python you cannot overload the = (assignment) operator
        self.value = value

Now from your example you can say

>>> a = Mutatable(1)
>>> def foo(bar):
...     bar.assign(2)
...
>>> foo(a)
>>> a.value
out: 2

As some of the other posters mentioned. General programming advice. Overuse of mutations creates for very hard to debug applications. Functions that return values and raise Exceptions are way easier to test and debug.

Upvotes: 2

nino_701
nino_701

Reputation: 692

If you want to change the value of a variable in some function without global or return instructions, then you can pass its name in function parameters and use globals() :

>>> def foo(bar):
    globals()[bar] = 3      

>>> x = 7
>>> x
7
foo('x')
>>> x
3

Upvotes: 1

fjarri
fjarri

Reputation: 9726

It is a consequence of two design decisions. First, functions arguments in Python are passed by assignment. That is, if you have a call like

foo(a)

it translates to, roughly

bar = a
<function body, verbatim>

That's why you can't just pass a pointer to any variable as you would in, say, C. If you want to mutate a function argument, it must have some mutable internal structure. That's where the second design decision comes in: integers in Python are immutable, along with other types including other kinds of numbers, strings or tuples. I don't know the original motivation behind this decision, but I see two main advantages:

  • easier for a human to reason about the code (you can be sure your integer does not magically change when you pass it to a function)
  • easier for a computer to reason about the code (for the purpose of optimization or static analysis), because a lot of function arguments are just numbers or strings

My personal opinion is that you should avoid functions that mutate their arguments where possible. At the very least, they should be methods and mutate the corresponding object. Otherwise the code becomes error-prone and hard to maintain and test. Therefore I fully support this immutability, and try to use immutable objects everywhere.

Upvotes: 1

Kasravnd
Kasravnd

Reputation: 107337

First off, every every thing in python is object (except some singleton and interns) and every object exist in a scope contain global, local, built-in and enclosing scopes. And the main purpose of using scopes is obviously preserving a set of command and script which are following a specific aim.

Therefore it's not reasonable to destroy this architecture by letting variables in different scopes to impact each other.

But in Python has provided us with some tools in order to make some variables available in upper scope1, like global statement.

Note: Regarding the second example, remember that changing a mutable object inside the function may impact the caller and that's because mutable objects like lists actually are a container of pointers to the actual objects and when you change one pointer it will affect on the main object.


1. The hierarchy of scopes in python from inner to outer is: Local, Enclosing, Global, Built-in. Known as LEGB manner.

Upvotes: 1

Related Questions