Is there a difference between the two? [duplicate] - python

This question already has answers here:
Different behaviour for list.__iadd__ and list.__add__
(3 answers)
Closed 9 years ago.
code A:
lst = [1, 2, 3]
for i in range(10):
lst+= ["42"]
code B:
lst = [1, 2, 3]
for i in range(10):
lst = lst + ["42"]
I know the output is the same, but is there a difference in the way the two lists are built?
What's happening in the back actually?

When you do
lst += ["42"]
You are mutating lst and appending "42" at the end of it. But when you say,
lst = lst + ["42"]
You are creating a new list with lst and "42" and assigning the reference of the new list to lst. Try this program to understand this better.
lst = ["1"]
print(id(lst))
lst += ["2"]
print(id(lst))
lst = lst + ["3"]
print(id(lst))
The first two ids will be the same, bu the last one will be different. Because, a new list is created and lst now points to that new list.
Not knowing the difference between these two will create a problem, when you pass a list as a parameter to a function and appending an item to it, inside the function like this
def mutate(myList):
myList = myList + ["2"] # WRONG way of doing the mutation
tList = ["1"]
mutate(tList)
print(tList)
you will still get ['1'], but if you really want to mutate myList, you could have done like this
def mutate(myList):
myList += ["2"] # Or using append function
tList = ["1"]
mutate(tList)
print(tList)
will print ['1', '2']

Related

Difference between + and += [duplicate]

This question already has answers here:
Why does += behave unexpectedly on lists?
(9 answers)
What exactly does += do?
(17 answers)
Closed 1 year ago.
Why it gives different outputs:
is there a difference between + and +=
def func1(lst1, lst2):
lst1 += lst2
lst1 = [1, 2, 3]
lst2 = ["a", "b"]
func1(lst1, lst2)
print(lst1)
and
def func1(lst1, lst2):
lst1 = lst1 + lst2
lst1 = [1, 2, 3]
lst2 = ["a", "b"]
func1(lst1, lst2)
print(lst1)
Thanks in advance
The difference here is that += changes the initial list lst1. Whilst the lst1 = lst1 + lst2 creates a new list and rewrites local reference lst1 which does not affect global object lst1. If you try printing lst1 inside the functions, both cases would give you the same result.
A good IDE will give you a hint, like so:
If you recognize the dark grey color of lst1, move your mouse over it and it will give you a hint. Here, the problem is that the local variable is not used, as explained by #Yevhen Kuzmovych.
+= can have a different implementation than +. That's the case for lists: += modifies the list inplace whereas + gives you a new list and using the same name on the left side makes that not so obvious.
It also says that you have a naming issue, called shadowing. Did you expect lst1 from the outer scope to update, because it has the same name? If you thought that, you need to read about scope. If you know another programming language, you also want to understand the difference between pass by value, pass by reference and pass by assignment (Python).
In your first example, you are passing a reference to lst1. Therefore, the increment affects the list that lst1 refers to.
In your second example, you're also passing a reference but the operation lst1 + lst2 creates a new list instance and lst1 subsequently points at that. Thus your original list is unaffected.
You need to decide if you really want lst1 modified or whether you want to know what the addition of the two lists looks like

what comes before "for i in range (...)" [duplicate]

This question already has answers here:
Understanding slicing
(38 answers)
Closed 2 years ago.
I have a simple question, looking at the following code:
letters = [hand[i]][:1] for i in range(5)]
What does the argument before 'for I in range(5)' do?? I can't seem to figure it out.
A simple list comprehension has three parts:
my_list = [A for B in C]
This translates exactly into:
my_list = []
for B in C:
my_list.append(A)
So the part before for determines what goes into the list you're creating.
In your case, you could also write it like this:
letters = []
for i in range(i):
letters.append(hand[i][:1]])
The upper piece of code is called list comprehension:
https://docs.python.org/3/tutorial/datastructures.html
So the upper code could be explicitly written out as:
hand # some data. From your code it should be a nested list, eq: hand = [ [...],[...],... ]
letters = []
for i in range(5): # iterates trough 0-4
element = hand[i][:1]
letters.append(element)
So this is just a very short way of constructing a list. You read it out lout like so:
For every i from range(5) take element(s) hand[i][:1] and assign it to a new list letters.
If your question is about the part hand[i][:1], then this is a slice from a nested list. For example:
hand = [
[0,1,2,3],
[4,5,6,7],
...
]
hand[0] == [0,1,2,3]
hand[0][:1] == [0]
hand[1][:1] == [4] # mind it is a slice, so you are left with a list!!

why using x in list and change x's value did not work in Python [duplicate]

This question already has answers here:
Can't modify list elements in a loop [duplicate]
(5 answers)
Closed 4 years ago.
Suppose I have a list nums = [1,3,2,5,6] and I want to subtract each element's value by 1. Now I wrote codes like
for i in nums:
i -= 1
However, when I print nums its values did not change. I'm wondering why it doesn't work, and whether there is an elegant way in Python to do this. Thank you!
i is a local variable and does not reflect the actual objects in nums, only their values. The best way to do this is to use a list comprehension:
nums = [i - 1 for i in nums]
If you need to retain references to nums:
nums[:] = = [i - 1 for i in nums]
Demo:
>>> nums = [1, 2, 3]
>>> [i - 1 for i in nums]
[0, 1, 2]
The for loop sets i to successive values in the list, not references into the list. There are a couple ways to accomplish what you want:
nums = [i-1 for i in nums]
Is one way. If you need to keep the same list object you could do:
for ndx in xrange(len(nums)):
nums[ndx] -= 1

Appending an empty list with list in recursive function

def permute(nums):
result = []
get_permute([], nums, result)
return result
def get_permute(current, num, result):
if not num:
result.append(current+[])
for i, v in enumerate(num):
current.append(num[i])
get_permute(current, num[:i] + num[i + 1:], result)
current.pop()
if __name__ == "__main__":
r = permute([1,2,3])
for perm in r:
print(perm)
What does current + [] do in result.append(current+[]) if I remove +[] it printing blank lists.
It's making a copy of the list. When you remove it, you run into the List of lists changes reflected across sublists unexpectedly problem, because the outer list contains many references to the same list, instead of references to many different lists.
You should be able to replace it with current.copy() (using Python >= 3.3) or list(current) to avoid similar confusion among future readers. (There are a lot of ways to copy a list. Pick the one you like and stick with it.)
What does the + [] do?
It generates a new list with the same contents as the old list.
>>> x = [1]
>>> id(x) == id(x + [])
False
>>> x == x + []
True
Why do I need this?
Whitout adding copies to your result, you would have the same list many times in your result and everytime you update that list, it affects your result.
>>> x = [1, 2]
>>> result = []
>>> result.append(x)
>>> x.append(3)
>>> result.append(x)
>>> result
[[1, 2, 3], [1, 2, 3]]
Some possible ways to make the could more readable would be
result.append(current[:])
or
result.append(list(current))
Why does it return blank lists if you remove the + []?
Because if you do not append copies to the result, there would be just one list in the result but multiple times. And you call .append(num[i]) on this list just as often as .pop(), which results in that list be empty.

How to cycle through items in an list and have each item get fed into a function [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Python: For each list element apply a function across the list
for example, let's say I have an array or list
myList = [a,b,c,d]
and I have a function that generates a random number.
How do I go through the list and have each of the
item in that list receives the random number generated by the
function and be added to the item?
So, say 'a' is the 1st in the list, 'a' goes into the function where a random number (let's say 5), is generated and adds itself to 'a' the result should be `[a+5, b+.......].
You use a list comprehension:
[func(elem) for elem in lst]
For your specific example, you can use an expression that sums the values:
[elem + func() for elem in myList]
where func() returns your random number.
Use map() function, that apply function to every item of iterable and return a list of the results:
def myfunc(x):
return x ** 2
>>> map(func, [1,2,3])
[1, 4, 9]
If you need one liner :-)
myList = [1,2,3,4]
[ i + map(lambda i: random.randint(10,20), myList)[index] for index, i in enumerate(myList) ]
I assume you're talking about integers. This little script should do what you want:
import random
def gen_rand(number):
generated = random.randint(1, 10) # you can specify whatever range you want
print generated
return number + generated
myList = [1,2,3,4,5]
print str(myList)
myList = [gen_rand(item) for item in myList]
print str(myList)
Or you could use the map function instead of the for loop.
Replace
myList = [gen_rand(item) for item in myList]
with
myList = map(gen_rand,myList)

Categories