This question already has answers here:
Why do these list operations (methods: clear / extend / reverse / append / sort / remove) return None, rather than the resulting list?
(6 answers)
Closed 5 months ago.
I want to attach a list to itself and I thought this would work:
x = [1,2]
y = x.extend(x)
print y
I wanted to get back [1,2,1,2] but all I get back is the builtin None. What am I doing wrong? I'm using Python v2.6
x.extend(x) does not return a new copy, it modifies the list itself.
Just print x instead.
You can also go with x + x
x.extend(x) modifies x in-place.
If you want a new, different list, use y = x + x.
or just:
x = [1,2]
y = x * 2
print y
x.extend(x) will extend x inplace.
>>> print x
[1, 2, 1, 2]
If you want a new copy of the list try:
x = [1,2]
y = x + x
print y # prints [1,2,1,2]
The difference is that extend modifies the list "in place", meaning it will always return None even though the list is modified.
Related
This question already has answers here:
Python assigning multiple variables to same value? list behavior
(13 answers)
Closed 4 months ago.
When initializing multiple variables in Python is seems that every variable is different (i.e. not a reference) :
>>>x = y = z = 6
>>>x=5
>>>y=0
>>>print(x,y,z)
>>>5 0 6
but when I am using a numpy array every variable is actually a reference:
import numpy as np
x = y = z = 6*np.ones(1)
x[0] = 5
y[0] = 0
print(x,y,z)
[0.] [0.] [0.]
Why am I seeing this difference?
This is down to a difference in types. Integers are not passed by reference, so each variable gets its own copy of the number. If you look at a different object like a list though:
x = y = z = [0,1,2]
x[0] = 2
print(x, y, x)
[2, 1, 2], [2, 1, 2], [2, 1, 2]
this is also passed by reference, so they all change together.
Strings and integers are the main examples I can think of that you the value, while everything else (I think) is a reference.
Interesting aside related to this: in place operations behave differently for strings and integers vs other objects. For example:
x = 1
print(id(x))
x += 1
print(id(x))
behaves differently to
y = []
print(id(y))
y += [1]
print(id(y))
You can see in the first instance a new object is now assigned to the x variable, while in the second the y variable is the same object.
You need to make copies:
a = 6*np.ones(1)
x, y, z = (a.copy() for _ in range(3))
# or directly
# x, y, z = (6*np.ones(1) for _ in range(3))
x[0] = 1
(x, y, z)
output:
(array([1.]), array([6.]), array([6.]))
x = [1,3,6,[18]]
y = list(x)
print(y)
x[3][0] = 15
x[1] = 12
print(x)
print(y)
In the above code, updating x[3][0] in x is reflected in y (which is the list of x), but the update in x[1] = 12 is not reflected in y
Why this is not getting updated in y?
A picture worth thousand words. Here is the picture that is missing:
(let's pretend forgetting all *terminology for a moment now)
Credits to all posts. Labor (of the wording & picturing) is mine.
First thing first, when you try to use list constructor to create y: list(x) or [:] it just produces a shallow copy (ie. the outermost container is duplicated, but the copy is filled with reference to the same item (as [18] shown in picture)
So later if you update x's [18] it will update the reference point - that's why both lists see the change of 15. But when you update other object, it directly change the integer object in the container x but not in y.
Lesson learned - Copies are shallow by Default! in Python.
# See different code example:
x = [1,3,6,[18]]
y = x[:] # new list, but it's shallow copy (last item)
print(x, id(x)) # different memory
print(y, id(y)) # but same content to start with
x[3][0] = 15 # assign new value - reflect in both x, y
x[1] = 12 # assign new value - only affect x
print(x, id(x))
print(y, id(y)) # last item got changed too; because sharing
https://i.imgur.com/3MJLTUE.png
What is happening is a shallow copy. When you wrote y=list(x), this created a reference from y to x, and not an actual copy. What you need is a deep copy, a copy that creates a new list(including nested lists) instead of referencing the old one. .copy() won't work, because nested lists are still references even though the rest of the copied list is a separate list.
Here is the code for a deep copy:
import copy
x=[1,3,6,[18]]
y=copy.deepcopy(x)
print(y)
x[3][0]=15
x[1]=12
print(x)
print(y)
By using list() you create a new reference (y) to the same addresses in memory that (x) is referring.
Element 1 in x and y is an integer which is immutable. Once you use x[1]=12 basically you create a new object in memory for number 12 and x[1] will refer to that object. However, y[1] still refers to previous object (i.e. 3).
Element 3 in in x and y is a list which is mutable. Once, you use x[3][0], it updates the same object in memory. So, both x and y reflect the change.
I hope I could convey the concept.
They do not behave differently. Changes to x are never reflected in y.
x = [1,3,6,[18]]
y = list(x)
print(y) # [1,3,6,[18]]
x[3] = [15]
print(y) # [1,3,6,[18]]
However, changes to the 1-element list are reflected both in x and in y:
z = [18]
x = [1,3,6,z]
y = list(x)
print(y) # [1,3,6,[18]]
z[0] = 15
print(y) # [1,3,6,[15]]
The reason why integers and lists are different, the reason why you don't see changes to integers reflected in y is because it's possible to make changes to a list, but it's not possible to make changes to int:
x = [1,3,6,[18]]
y = list(x)
print(y) # [1,3,6,[18]]
3 = 12 # SyntaxError: cannot assign to literal here.
In python, every type is either mutable or immutable. Lists are mutable; integers are immutable.
This question already has answers here:
Program that asks user for numbers and outputs the sum and the amount of numbers entered
(4 answers)
Closed 6 months ago.
I am trying to add numbers in python. I know that it would be x + 3 when you are adding it, but when I try to do it with the program I am writing, it doesn't work out how I want it to be!
Here is the code:
x = 0
list = []
for i in range (1,100):
y = x + 3
list.append(y)
print (list)
and the output we get is :
[3,3,3,3,3,3...]
When I want it to be:
[3,6,9,12,15]
Can someone please tell me what I am doing wrong?
Thanks!
You need to assign the result back to x so that it accumulates the values. You keep adding to the original value of x, since x never changes.
x = 0
l = []
for i in range(1, 100):
x += 3
l.append(x)
print(l)
BTW, don't use list as the name of a variable. It's the name of a Python built-in function.
Your not increasing or incrementing the variable x. So after the statement list.append(y), in a new line, add x+=3
You don't need the variable x,
Change the line y=x+3 to y=i*3
In your script you are not redefining the value of x each time so you are doing 0+3 countless times. I is the index of the loop so will increase after each iteration, allowing you to have an increasing value in the list output
You can write it in one line like this:
[x for x in range(1, 100) if x % 3 == 0]
or:
[x*3 for x in range(1, 100)]
You can do this:
you are not updating the x so you keep adding the originalx value. so x have to be updated. but since you have y you can do this.
y = 0
mylist = []
for i in range (1,100):
y += 3
mylist.append(y)
print (mylist)
or do this you can just update the x value, then it works.
x = 0
mylist = []
for i in range (1,100):
y = x + 3
x += 3 #update the x variable
mylist.append(y)
print (mylist)
And don't use list as the name of a variable. It's the name of a Python built-in function. In python so use another word like mylist or something.
this will help
x = 0
lst = []
for i in range (1,100):
y = x+i*3
lst.append(y)
print(list)
x is always 0, so you keep running y = 0 + 3, then adding that to the list
You dont need a y variable at all, you can run this in your loop
x += 3
lst.append(x)
Or, maybe simpler
lst = [3*x for x in range(1, 100)]
So basically what i want my script to do is output something like
somelist = ([0,0],[0,0])
given x = 2.
so if x were 3 it would be
somelist = ([0,0,0],[0,0,0],[0,0,0])
what I've come up with so far is
somelist = ([0] * x) * x
but this simply returns
somelist = [0,0,0,0]
Anybody know of a simple way to do this?
The old singleton tuple issue. Add a comma or else the parentheses will be meaningless (interpreted merely as precedence/grouping markers):
somelist = ([0] * x,) * x
# ^--- makes all the difference
This question already has answers here:
Explanation of how nested list comprehension works?
(11 answers)
Closed 6 years ago.
Can someone please explain the meaning the syntax behind the following line of code:
temp3 = [x for x in temp1 if x not in s]
I understand it's for finding the differences between 2 lists, but what does the 'x' represent here? Each individual element in the list that is being compared? I understand that temp1 and s are lists. Also, does x for x have to have the same variable or could it be x for y?
[x for x in temp1 if x not in s]
It may help to re-order it slightly, so you can read the whole thing left to right. Let's move the first x to the end.
[for x in temp1 if x not in s yield x]
I've added a fake yield keyword so it reads naturally as English. If we then add some colons it becomes even clearer.
[for x in temp1: if x not in s: yield x]
Really, this is the order that things get evaluated in. The x variable comes from the for loop, that's why you can refer to it in the if and yield clauses. But the way list comprehensions are written is to put the value being yielding at the front. So you end up using a variable name that's not yet defined.
In fact, this final rewrite is exactly how you'd write an explicit generator function.
def func(temp1, s):
for x in temp1:
if x not in s:
yield x
If you call func(temp1, s) you get a generator equivalent to the list. You could turn it into that list with list(func(temp1, s)).
It iterates through each element in temp1 and checks to see if it is not in s before including it in temp3.
It is a shorter and more pythonic way of writing
temp3 = []
for item in temp1:
if item not in s:
temp3.append(item)
Where temp1 and s are the two lists you are comparing.
As for your second question, x for y will work, but probably not in the way you intend to, and certainly not in a very useful way. It will assign each item in temp1 to the variable name y, and then search for x in the scope outside of the list comprehension. Assuming x is defined previously (otherwise you will get NameError or something similar), the condition if x not in s will evaluate to the same thing for every item in temp1, which is why it’s not terribly useful. And if that condition is true, your resulting temp3 will be populated with xs; the y values are unused.
Do not take this as saying that using different variables in a list comprehension is never useful. In fact list comprehensions like [a if condition(x) else b for x in original_sequence] are often very useful. A list comprehension like [a for x in original_sequence if condition(x)] can also be useful for constructing a list containing exactly as many instances of a as the number of items in original_sequence that satisfy condition().
Try yourself:
arr = [1,2,3]
[x+5 for x in arr]
This should give you [6, 7, 8] that are the values on the [1,2,3] list plus 5. This syntax is know as list comprehension (or mapping). It applies the same instructions to all elements on a list. Would be the same as doing this:
for x in arr:
arr += 5
X is same variable and it is not y. It works same as below code
newList = []
for x in temp1:
if x not in s:
newList.append(x)
So x for x, here first is x which is inside append in code and x after for is same as for x in temp1.