Function editing lists in Python [duplicate] - python

This question already has answers here:
How do I pass a variable by reference?
(39 answers)
Closed 7 years ago.
So basically i've observed that in python3 if i do something like
a = 5
def addFive(x):
x+=5
return x
print(addFive(a),a)
The output will be "10 5" since a is not changed by the function.
However the same does not happen for lists:
a = [1,2,3]
def b(x):
z = x
z.append(10)
b(a)
print(a)
When i run the function it changes the actual list.
Now to my Question: Why does this happen, where can i read up more about this(Honestly have no idea how to word my google search) and how can i avoid this. Please feel free to redirect me to other articles as this could be a common problem but I honestly couldn't find anything similar.
Thanks in advance :)

Use the copy module.
import copy
a = [1,2,3]
def b(x):
z = copy.deepcopy(x)
z.append(10)
return z
b(a)
print(a)
This prints
[1, 2, 3, 10]
[1, 2, 3]

Each element in a Python list is a location in memory, so when you modify an element, you're actually modifying that reference in memory. So if you're familiar with C++, passing a list into a function in Python, is similar in concept to passing by reference.

Related

Can you directly alter the value of a non-list argument passed to a function? [duplicate]

This question already has answers here:
How do I pass a variable by reference?
(39 answers)
Closed 13 days ago.
This snippet of python code
def changeValue(x):
x = 2*x
a = [1]
changeValue(a[0])
print(a[0])
Will print the result "1" when I would like it to print the result "2". Can this be done by only altering the function and no other part of the code? I know there are solutions like
def changeValue(x):
x[0] = 2*x[0]
a = [1]
changeValue(a)
or
def changeValue(x):
return 2*x
a = [1]
a[0] = changeValue(a[0])
I am wondering if the argument passed as-is can be treated as a pointer in some sense.
[edit] - Just found a relevant question here so this is likely a duplicate that can be closed.
No it's not possible. If you pass a[0], it's an int and it can't be mutated in any way.
If the int was directly in the global namespace, you could use global keyword. But it's not. So again no.

del() vs del statement in python [duplicate]

This question already has answers here:
Why does del (x) with parentheses around the variable name work?
(2 answers)
"assert" statement with or without parentheses
(6 answers)
Closed 4 years ago.
The community reviewed whether to reopen this question 3 months ago and left it closed:
Original close reason(s) were not resolved
>>> li = [1, 2, 3, 4]
>>> li
[1, 2, 3, 4]
>>> del li[2] #case 1
>>> li
[1, 2, 4]
>>> del(li[2]) # case 2
>>> li
[1, 2]
>>> del (li[1]) # case 3
>>> li
[1]
>>>
One of my professors used case 2 to delete item from list.
As per python documentation case 1 is right and there is also another syntactic way exist from this answer so case 3 also right, but as per my knowledge there is no del method exist in python, how case 2 is valid. I searched whole python documentation but could not find it.
Update:
if i write del method myself in my module and use case 2 at same time, how python interpreter differentiates between them or will it through an error, although i never tried until now
All of them are the same, del is a keyword as yield or return, and (list[1]) evaluates to list[1]. So del(list[1]) and del (list[1]) are the same. For the base case, since you dont have the () you need to force the extra space, hence del list[1].
EDIT: You cannot redifine del since it is a language keyword.
The parenthehis is not mandatory with keyword (like if or del), but can put some if you want.
it's exactly the same thing

Why include include the entire `lambda` expression in list comprehension? [duplicate]

This question already has answers here:
Callback function tkinter button with variable parameter [duplicate]
(2 answers)
Closed 4 years ago.
In his writeup on Python programming mistakes, Martin Chikilian includes the following to illustrate misconceptions regarding variable lifetimes inside closures:
def create_multipliers():
return [lambda x: i * x for i in range(5)]
for multiplier in create_multipliers():
print(multiplier(2))
The output is understandably surprising to some as i maintains its final value (4) in the closure between calls to multiplier. Martin includes a hack to get the desired output (please see his article for details).
What I'm wondering about is what is being accomplished by including the entire lambda in the list comprehension? Is it a common idiom in some field such as scientific computing? Because, to me, the following is much easier to understand:
def create_multiplier():
return lambda x: [i * x for i in range(5)]
multiplier = create_multiplier()
print(multiplier(2))
Output:
[0, 2, 4, 6, 8]
The output from the 2nd version roughly matches that listed as desirable by Martin. So what's going on here?
They accomplish different things. The former returns a list of lambas that return numbers and the latter returns a lambda that returns a list of numbers. You can imagine different use cases for each.

Pass-by-object-reference and mutability [duplicate]

This question already has answers here:
How do I pass a variable by reference?
(39 answers)
Closed 6 years ago.
Much has been written about python pass-by-object-reference. But it is confusing to read threads like this or this.
In those threads, some say mutability is important, while others say that mutable or immutable objects are handled the same way.
I have a simple question, why are the contents of a not modified in the first snippet of code and modified in the second? According to this explanation of pass-by-object-reference, shouldn't the contents of the reference be modified in both cases?
def fn(b):
b += 1
a = 2
fn(a)
print(a)
def fn(b):
b += [4]
a = [2]
fn(a)
print(a)
shouldn't the contents of the reference be modified in both cases?
No, since int objects are immutable.
You don't even need functions to demonstrate this.
Consider the following:
a = 1
print(id(a))
a += 1
print(id(a))
>> 496418832
496418848
We are obviously getting a new object.
Compare to:
a = [1]
print(id(a))
a += [2]
print(id(a))
>> 36641608
36641608
Note a is still referencing the same object in this case.

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.

Categories