List value changes after execution of for loop - python

I have a list "a". after executing following for loop list values are changed
a=[1,2,3]
for a[0] in a:
print(a[0])
print(a) #it prints [3, 2, 3]

When you write
for i in [1,2,3]:
print i
i = 1 and then 2 and then 3 for each iteration. So if you execute this code
a=[1,2,3]
for a[0] in a:
print a[0]
print a
Output:
1
[1, 2, 3]
2
[2, 2, 3]
3
[3, 2, 3]
You can clearly see that a[0] is first 1, then 2 and finally 3, so 'a' becomes [1,2,3] in the end.

I think you want to display all the values ​​in your list.
If that's what you want to do, I advise you to use enumerate like this.
a=[1,2,4]
for index, value in enumerate(a):
print(value)
print(a)
So no value in your list is changed.

Here's what your code does split up in single commands. Maybe this way you can better understand what's going on:
a = [1,2,3]
# for loop begins
a[0] = a[0] # a is now [1,2,3]
print(a[0]) # prints 1
a[0] = a[1] # a is now [2,2,3]
print(a[0]) # prints 2
a[0] = a[2] # a is now [3,2,3]
print(a[0]) # prints 3
# for loop ends
print(a) # prints [3,2,3]
In short: don't ever use an element of a list as a loop variable to iterate over that list with. It makes no sense, except for very special cases.

Related

Why python call by reference is so unruly

arr = [1]
def f1(lst):
lst.append(2)
print(lst)
lst = 2
print(lst)
f1(arr)
print(arr) # [1,2]
why python call by reference parameter does not change to value?
what does lst variable indeicating when do "lst = 2"
(not connected to arr?)
Assigning lst = 2 doesn't affect the value of arr. In fact, python doesn't do "call by reference" at all.
Annotating your code with comments that might help clear it up:
arr = [1]
def f1(lst):
# lst and arr both refer to the same [1] list at this point.
# Two different and independent names for the same object.
lst.append(2) # appends 2 to [1], aka lst, aka arr
print(lst) # lst/arr is now [1, 2]
lst = 2 # reassign the name 'lst' to the value 2!
# At this point, lst refers to 2 instead of [1, 2].
# lst and arr are no longer connected.
# arr is still [1, 2] even though lst is 2.
print(lst) # indeed, lst is now 2
# but arr is still [1, 2], as seen below:
f1(arr)
print(arr) # [1,2]
https://nedbatchelder.com/text/names.html is highly recommended reading on this topic! The main thing to understand is that lst and arr are just different names that at different points in the code might refer to the same value or different values.
When you call lst.append, you are modifying the value that lst is a name for, which arr also happens to be a name for. When you say lst = 2, you are rebinding the name lst, but you are not modifying the value that it previously referred to (and to which arr still refers).

Print a lists element in a single line but dont use a loop

is there a way to print a list for its element in a single line without using a loop ?
a = [1, 2, 3]
output -
1 2 3
the only condition is not to use a loop. So basically maybe taking list as an object and convert it to another object like the output and print. Just dont want to use refer the list element by element like in a for or any other loop.
As seen in that post from buran, you can use this line:
print(*a)
A way using indexes simply is:
print(a[:])
As a comparison of both:
>>> a = [1, 2, 3]
>>> print(a)
[1, 2, 3]
>>> print(a[:])
[1, 2, 3]
>>> print(*a)
1 2 3
Therefore, *a is the answer you are looking for.
Note: * before a variable does an "unzip" or "depackage", meaning it will return elements of a tuple/list/string as 1 by 1.
Hope this was useful ;)

I want to know list parmeters in python function like a[:]

pset = []
def powe(a):
powehelp(a,0)
def powehelp(a, ind):
if len(a) == ind:
pset.append(a)
return
powehelp(a[:], ind+1)
a.pop(ind)
powehelp(a[:],ind)
powe([1,2,3])
print(pset)
This code creates its subset, and in this code I want to know why I can't use powehelp(a, ind+1) instead of powehelp(a[:], ind+1)?
I know that a[:] means get all the values ​​of list a.
When using a, the result is [[], [], [], []].
Your powehelp function uses pop, which means it alters the list it is given.
If you pass a into it, it is a that gets altered, and evidently ends up empty.
a[:] creates a copy of a. If you pass a[:] into powehelp, your original list a is unaffected.
The given a is a list in itself, and so appending a list to a list would make a nested list.
a = [1, 2, 3]
b = []
b.append(a)
b
[[1, 2, 3]]
When you pset.append(a) you insert the list a into the endtail of the list pset so you result is a nested list. If I understand your requirement correctly, you're looking to concatenate your lists, as in:
c = [4, 5, 6]
a + c
[1, 2, 3, 4, 5, 6]

How to access the nested list items in python with out creating a new list?

Is there any way that i can access the items of nested list ?
# Here a is the nested list
a = [1, 2, [3,4]]
a[0] == 1
a[1] == 2
a[2] == [3,4]
# k is the new list
k = a[2]
k[0] == 3
k[1] == 4
you said without creating a new list
I would like to explain a bit about that for you. By declaring b=a[2] you are definitely not creating a new list. Check this out in your interpreter.
>>> a = [1,2,[3,4]]
>>> b = a[2]
>>> hex(id(a[2]))
'0x7f1432fcd9c8'
>>> hex(id(b))
'0x7f1432fcd9c8'
hex(id(your_variable)) just returns the address of the variable.
'0x7f1432fcd9c8' is the address of a[2] and b. Did you notice how they both are the same?
>>> b=a[:]
>>> hex(id(a))
'0x7f1431850608'
>>> hex(id(b))
'0x7f1432fb9808'
b=a[:] this only creates a fresh copy. Notice how addresses are different.
But look at this one below.
>>> a
[1, 2, [3, 4]]
>>> b=a
>>> hex(id(a))
'0x7f1431850608'
>>> hex(id(b))
'0x7f1431850608'
Same addresses. What does this mean ? It means in Python only the reference (i.e address of memory of the value is assigned to variables. So remember not to forget this. Also
To access elements in your nested loops use subscripts.
>>> a = [1,2,[3,4],[[9,9],[8,8]]]
>>> a[1]
2
>>> a[2]
[3, 4]
>>> a[2][0]
3
>>> a[3][1]
[8, 8]
>>> a[3][1][0]
8
Accessing elements this way is done in O(1) time so it is the fastest way possibile.
You can access it by providing two subscripts, like this:
a = [1, 2, [3,4]]
a[2][0] == 3
a[2][1] == 4
Lists in python are indexed from 0, not 1.
Do this instead.
# Here a is the nested list
a = [1, 2, [3,4]]
a[0] == 1
a[1] == 2
a[2] == [3,4]
# k is the new list
k = a[2]
k[0] == 3
k[1] == 4
You can also access the nested list by using the following syntax:
a[2][0] # => 3
a[2][1] # => 2
As you concern seem to be that you are making a new list: stop worrying you are not.
After
k = a[2]
both k and a[2] refer to the same list. Nothing new is created.
You can easily verify that by changing k[0] to something different than the element 3 it already has in that position:
k[0] = 5
and then
print(a)
which gives
[1, 2, [5, 4]]
If you wanted to create a new list you would have to explicitly do something like:
k = a[2][:]

Removing elements from a List in Python

I'm using python 3.4 and just learning the basics, so please bear with me..
listA = [1,2]
for a in listA:
listA.remove(a)
print(listA)
What is suppose is I get an empty list, but what I get is a list with value '2'. I debugged the code with large no. of values in list and when the list is having a single element the for loop exit.
Why is the last element not removed from the list..?
You should not change a list while iterating over it. The indices of the list change as you remove items, so that some items are never evaluated. Use a list comprehension instead, which creates a new list:
[a for a in list if ...]
In other words, try something like this:
>>> A = [1, 2, 3, 4]
>>> A = [a for a in A if a < 4] # creates new list and evaluates each element of old
>>> A
[1, 2, 3]
When you use a for-loop, an internal counter is used. If you shift the remaining elements to the left while iterating over the list, the left-most element in the remaining list will be not be evaluated. See the note for the for statement.
That happens because the length of the for is evaluated only at the beginning and you modify the list while looping on it:
>>> l = [1,2,3]
>>> l
[1, 2, 3]
>>> for a in l:
print(a)
print(l)
l.remove(a)
print(a)
print(l)
print("---")
1
[1, 2, 3]
1
[2, 3]
---
3
[2, 3]
3
[2]
---
>>>
See? The value of the implicit variable used to index the list and loop over it increases and skip the second element.
If you want to empty a list, do a clear:
>>> l.clear()
>>> l
[]
Or use a different way of looping over the list, if you need to modify it while looping over it.
As mentioned by #Justin in comments, do not alter the list while iterating on it. As you keep on removing the elements from the list, the size of the list shrinks, which will change the indices of the element.
If you need to remove elements from the list one-by-one, iterate over a copy of the list leaving the original list intact, while modifying the duplicated list in the process.
>>> listA = [1,2,3,4]
>>> listB = [1,2,3,4]
>>> for each in listA:
... print each
... listB.remove(each)
1
2
3
4
>>> listB
[]

Categories

Resources