Python pass by value [duplicate] - python

This question already has answers here:
How do I pass a variable by reference?
(39 answers)
Emulating pass-by-value behaviour in python
(8 answers)
Closed 4 years ago.
I'm a beginner for Python. I want to know some cases to pass by values instead of references. Assume we have the class:
class myC():
def __init__(self, x):
self.val = x
and the functions:
def myF1(myc):
myc.val = 1
def myF2(myDict):
myDict['a'] = 0
if we define the variable and call the function:
a = myC(0)
myDict = {}
myF1(a)
myF2(myDict)
The value of the variable a and myDict will change since both user defined class and dictionary are mutable types. Is there ant method that just pass the value of the variable so that the variable itself won't change? If there are multiple ways, please let me know all of them. Thank you very much.

Python always passes by value. However the values are references. The only value type you have in python is "reference". Variables are names and values are references.
Here is proof that python is passing by value:
def myfn(x):
x = 2
a = {}
myfn(a)
If python passed a reference to the function, the function code would modify a by making it refer to the integer object 2, but that doesn't happen. Python only passes the value (which is a reference) to the function, and now x inside the function is storing that reference.
x is a new reference to the same object, but making x store a reference to something else won't modify a. There is no way to modify what reference the a name is holding. You can modify the dict object, but you can't change the value of a (which is a reference to the dict)
If you want a new object, you have to explictly copy it. Some immutable objects like integers have implicit copying because they return a new object on operations:
a = 5
a = a + 2
In this example a + 2 semantically creates and returns a new int object, which the name a now stores a reference to. 5 and 2 are not modified (they are immutable)

Related

How to pass a specific value from Tuple into a function [duplicate]

This question already has answers here:
Getting one value from a tuple
(3 answers)
Closed 2 years ago.
variable1 = 1
variable2 = 2
a_tuple = (variable1, variable2)
def my_function(a):
pass
my_function(a_tuple(variable1))
Is there a way I can pass a specific value from a tuple into a function? This is a terrible example, but all I need to know is if I can pass variable1 from the tuple into the function, I understand in this instance I could just pass in variable 1, but its for more complicated functions that will get its data from a tuple, and I don't like the look of that many variables, too messy.
variable1 = 1
variable2 = 2
a_tuple = (variable1, variable2)
def my_function(a):
pass
my_function(*a_tuple)
This code would obviously provide an error as it unpacks the tuple and inserts 2 variables, to make this work in my program I would need a way to pass either variable1 or variable2 into the function. My question is can I define exactly which items from a tuple are passed into the function when calling the function? Latest version of Python if it matters.
P.S. I wrote print("hello world") for the first time 7 days ago, this is my first language and my first question I couldn't find an answer to. Go easy on me, and thank you for your time.
In the code you provided you don't have a tuple you have a list. But it is still pretty much the same.
In your example lets say that you wanted to pass the first variable you would do it like this:
my_function(a_tuple[0])
If you don't understand why there is a zero here and how does this work I highly suggest learning about lists before functions.
You just need to access individual elements of the tuple, using index notation:
my_function(a_tuple[0])
or
my_function(a_tuple[1])
You could, if you wanted, write a new function which takes a tuple and an index, and calls my_function with the appropriate element:
def my_other_function(tuple, index):
return my_function(tuple[index])
But I don't see how there would be much gain in doing that.
you can index a tuple or use the index method.
def my_function(a):
pass
my_function(a_tuple[0])
if you want to get the index of a value use the index() method
a_tuple.index(variable1) #this will return 0

Python calling function by string name from code [duplicate]

This question already has answers here:
How do I create variable variables?
(17 answers)
Closed 7 years ago.
Here is what I would like to be able to do:
I have a file called functions, with lots of functions. The functions are all essentially the same, functionally speaking (i.e., they are all of the form: pandas.Dataframe -> pandas.Dataframe). Obviously, they do different things to the Dataframe, so in that sense they are different.
I'd like to be able to pass my main function a list of strings, which would be the actual function names in the module, and have my program translate the strings into function calls.
So, basically, instead of:
functions = [module.functionA, module.functionB, module.functionC]
x = g(functions)
print(x)
> 'magical happiness'
I would have:
function_strings = ['functionA','functionB','functionC']
functions = interpret_strings_as_function_calls(module,function_strings)
x = g(functions)
print(x)
> 'magical happiness'
Is there a way to do this? Or do I need to write a function in the module that matches each string with it's corresponding function? i.e.:
def interpret_strings(function_string):
if function_string == 'functionA':
return module.functionA
elif function_string == 'functionB':
return module.functionB
etc.
(or in a switch statement, or whatever)
You can use getattr(module, function_string).

Are Python arguments passed by reference? [duplicate]

This question already has answers here:
How do I pass a variable by reference?
(39 answers)
Closed 7 years ago.
In detail, my question is this:
Given the following code,
x = 10
def func(x):
x = x+1
def main():
print(x)
func(x)
print(x)
if __name__ == '__main__':
main()
On running this I get:
10
10
Does this mean that Python does not pass values by reference?
And I did check through the other question of the sort, and most(if not all) included analogies of lists or other such examples.
Is it possible to explain this in simple terms, like just a simple integer?
Ps. I am a beginner to coding.
Thanks
If you are coming from a background such as C or C++, which I did, this can be maddening until you figure it out.
Python has names, not variables, and names are bound to objects. Effectively, you can think of all 'variables' or names, as being pointers to python objects.
In python, integers, floats, and strings are immutable. So when you do the following:
x = 10
x = x + 1
You are first binding the name x to the integer 10, then when you evaluate x + 1 you get a new object 11 and then you bind x to that object. Your x inside the function body is local to the function, and when you bind it to 11, the global x remains bound to 10.
If you were to pass a list to the function, and append something to the list, that list would be modified. A list in python is a mutable object. All names bound to the list would refer to the modified list.
As a result, when you pass mutable objects it may seem as if you are passing by reference, and when you pass immutable objects it may seem like you are passing by value.

Wierd Behavior Appending to list inside function [duplicate]

This question already has answers here:
How do I pass a variable by reference?
(39 answers)
Closed 8 years ago.
def test(list2):
list2.append(1)
print len(list2)
print len(LIST1)
LIST1 = [1]
while len(LIST1) < 9:
test(LIST1)
Please explain why 'LIST1' is increasing in size if I'm appending to 'list2', isn't variables inside functions local? And above all, how can I circumvent this?
The same happens if I make a new variable:
def test(arg_list):
list2 = arg_list
list2.append(1)
print len(list2)
print len(LIST1)
LIST1 = [1]
while len(LIST1) < 9:
test(LIST1)
No, parameters passed to a function are by reference, and in the second example the local variable is yet another reference to the same list. Parameter passing and variable assignment do not create copies of the list, only references to the same object. In other words: anything you do to an object being referenced inside the function (say, a list) will be reflected on the object itself once the function exits - the function parameter and the object "outside" the function are one and the same.
How can you circumvent this? well, if it fits your usage scenario you can simply copy the list before passing it as a parameter, like this:
test(LIST1[:])
The above will create a new, different list (it's a shallow copy, though ... for performing a deep copy use copy.deepcopy), which you can safely modify inside the function, as the list "outside" the function will remain unchanged.

Mutable default arguments in Python [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
“Least Astonishment” in Python: The Mutable Default Argument
I have written the following python program:
#!/usr/bin/env python
def bug( numbers = [] ):
numbers.append( 1 )
return numbers
print bug()
print bug()
The result i would expect is
[1]
[1]
But i got
[1]
[1, 1]
Is this a bug?
No, this is not a bug and this behaviour has been around in Python for a very long time.
The problem is that the list object is mutable, i.e. you can change it, and when you call a function you don't get a new default value. What's happening is this:
def bug( numbers = [] ):
numbers.append( 1 )
return numbers
At this point the function bug has been created and the list that is default value for numbers created.
print bug()
Now we've called bug once and added 1 to the list that was created when the function was defined.
print bug()
When we call the function again we get the same list as before so we get two 1s added to the list.
The usual solution is to define your function as follows:
def bug(numbers = None):
if numbers is None:
numbers = []
numbers.append(1)
return numbers
Read this for more details.
numbers=[] is evaluated only once (when the function is defined). So it's always the same list.
To avoid this, change the function like this:
def not_a_bug(numbers=None):
if numbers is None:
numbers = []
numbers.append(1)
return numbers

Categories