Reputation: 15423
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 :
Is there such method? (or alternative?)
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
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
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
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:
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
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