I am trying to append objects to the end of a list repeatedly, like so:
list1 = []
n = 3
for i in range(0, n):
list1 = list1.append([i])
But I get an error like: AttributeError: 'NoneType' object has no attribute 'append'. Is this because list1 starts off as an empty list? How do I fix this error?
This question is specifically about how to fix the problem and append to the list correctly. In the original code, the reported error occurs when using a loop because .append returns None the first time. For why None is returned (the underlying design decision), see Why do these list operations return None, rather than the resulting list?.
If you have an IndexError from trying to assign to an index just past the end of a list - that doesn't work; you need the .append method instead. For more information, see Why does this iterative list-growing code give IndexError: list assignment index out of range? How can I repeatedly add elements to a list?.
If you want to append the same value multiple times, see Python: Append item to list N times.
append actually changes the list. Also, it takes an item, not a list. Hence, all you need is
for i in range(n):
list1.append(i)
(By the way, note that you can use range(n), in this case.)
I assume your actual use is more complicated, but you may be able to use a list comprehension, which is more pythonic for this:
list1 = [i for i in range(n)]
Or, in this case, in Python 2.x range(n) in fact creates the list that you want already, although in Python 3.x, you need list(range(n)).
You don't need the assignment operator. append returns None.
append returns None, so at the second iteration you are calling method append of NoneType. Just remove the assignment:
for i in range(0, n):
list1.append([i])
Mikola has the right answer but a little more explanation. It will run the first time, but because append returns None, after the first iteration of the for loop, your assignment will cause list1 to equal None and therefore the error is thrown on the second iteration.
I personally prefer the + operator than append:
for i in range(0, n):
list1 += [[i]]
But this is creating a new list every time, so might not be the best if performance is critical.
Note that you also can use insert in order to put number into the required position within list:
initList = [1,2,3,4,5]
initList.insert(2, 10) # insert(pos, val) => initList = [1,2,10,3,4,5]
And also note that in python you can always get a list length using method len()
Like Mikola said, append() returns a void, so every iteration you're setting list1 to a nonetype because append is returning a nonetype. On the next iteration, list1 is null so you're trying to call the append method of a null. Nulls don't have methods, hence your error.
use my_list.append(...)
and do not use and other list to append as list are mutable.
Related
I am trying to append objects to the end of a list repeatedly, like so:
list1 = []
n = 3
for i in range(0, n):
list1 = list1.append([i])
But I get an error like: AttributeError: 'NoneType' object has no attribute 'append'. Is this because list1 starts off as an empty list? How do I fix this error?
This question is specifically about how to fix the problem and append to the list correctly. In the original code, the reported error occurs when using a loop because .append returns None the first time. For why None is returned (the underlying design decision), see Why do these list operations return None, rather than the resulting list?.
If you have an IndexError from trying to assign to an index just past the end of a list - that doesn't work; you need the .append method instead. For more information, see Why does this iterative list-growing code give IndexError: list assignment index out of range? How can I repeatedly add elements to a list?.
If you want to append the same value multiple times, see Python: Append item to list N times.
append actually changes the list. Also, it takes an item, not a list. Hence, all you need is
for i in range(n):
list1.append(i)
(By the way, note that you can use range(n), in this case.)
I assume your actual use is more complicated, but you may be able to use a list comprehension, which is more pythonic for this:
list1 = [i for i in range(n)]
Or, in this case, in Python 2.x range(n) in fact creates the list that you want already, although in Python 3.x, you need list(range(n)).
You don't need the assignment operator. append returns None.
append returns None, so at the second iteration you are calling method append of NoneType. Just remove the assignment:
for i in range(0, n):
list1.append([i])
Mikola has the right answer but a little more explanation. It will run the first time, but because append returns None, after the first iteration of the for loop, your assignment will cause list1 to equal None and therefore the error is thrown on the second iteration.
I personally prefer the + operator than append:
for i in range(0, n):
list1 += [[i]]
But this is creating a new list every time, so might not be the best if performance is critical.
Note that you also can use insert in order to put number into the required position within list:
initList = [1,2,3,4,5]
initList.insert(2, 10) # insert(pos, val) => initList = [1,2,10,3,4,5]
And also note that in python you can always get a list length using method len()
Like Mikola said, append() returns a void, so every iteration you're setting list1 to a nonetype because append is returning a nonetype. On the next iteration, list1 is null so you're trying to call the append method of a null. Nulls don't have methods, hence your error.
use my_list.append(...)
and do not use and other list to append as list are mutable.
I've got the list student:
student = ["test_name","1","6"]
And I've got the read data sublist:
read_data = [["test_name","1","2","5","9"],["test_name_2","1","5","2","10"]]
I've written the following nested loop to return the index of a sublist (referred to as x) in read_data if student[0] == x[0]:
lst = [read_data.index(x) for x in read_data if x[0] == student [0]]
So I'm looping through each item in read data and (if x[0] == student[0]) the index of the sublist should be stored in lst.
When I try to use this in the index parameter of a list to insert data like so:
read_data[read_data.index(x) for x in read_data if x[0] == student[0]].insert(2,student[0])
I get an error saying generators can't be used for indexes - why not?
I can obviously just use the integer stored in lst but this seems inefficient - surely there's a way to do this on one line.
Is there some better alternative method to checking if a string is in any of a read_data's sublists and getting the index of this sublist?
In the assignment to lst you are creating a list. But in the snippet below that, you have merely taken the interior of that list expression and are trying to use it as an index. To fix your specific example, you would need to change:
read_data[iter_expr]
to:
read_data[[iter_expr][0]]
That will use the first value in the list as the index.
There are better ways to do this, but this is probably the smallest change that will fix the specific problem you asked about.
I dont know why you would want to do this but then you need to put brackets around the list comprehension and get index the first match of it like this:
read_data[[read_data.index(x) for x in read_data if x[0] == student[0]][0]].insert(2, student[0])
Remember if the list comprehension produces an empty list, you will encounter an IndexError.
I am trying to use extend to save data calculated from loop iterations. However, I get the error 'numpy.int64' object is not iterable
x_hat1= commpy.channels.bsc(x[1],0.2)
Distance = []
for i in range(1, 6):
Distance.extend(hamming_distance(x_hat1,x[i]))
So, I tried adding the loop inside the extend itself as follows
Distance.extend(value for i in range(1, 6), hamming_distance(x_hat1,x[i]))
But I get the error Generator expression must be parenthesized if not sole argument. I checked the parenthesis a couple of times and they are correct. So, I don't know what is wrong.
Briefly, I want to find the hamming distances between one vector and several ones, and save it in the list "Distance" to use it later on.
Thanks
Your problem is extend expects a list as an argument. If you want to use a normal for loop, either make a single element list:
x_hat1= commpy.channels.bsc(x[1],0.2)
Distance = []
for i in range(1, 6):
Distance.extend([hamming_distance(x_hat1,x[i])])
or use append instead of extend: Distance.append(hamming_distance(x_hat1,x[i])).
If you want to use an implicit for loop, as in your second case, you simply need to restructure your statement.
The reference to i should come before the implicit loop:
Distance.extend(hamming_distance(x_hat1,x[i]) for i in range(1, 6))
Any of these options will work, it's up to you which you would prefer. (Personally the implicit loop is my favorite. It's a one-liner, not to mention much more pythonic than the straight for loop.)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
More info on list.extend vs. the list.append functions in python (as that was your main confusion):
Append:
Appends a single object to the end of a list
Examples:
>>myList = [1,2,3]
>>myList.append(4)
>>myList
[1,2,3,4]
BUT should not be used to add a whole list of elements
>>myList = [1,2,3]
>>myList.append([4,5,6])
>>myList
[1,2,3,[4,5,6]]
More info/examples:
http://www.tutorialspoint.com/python/list_append.htm
Extend:
Extends a list by using list.append on each element of the passed list
Examples:
>>myList = [1,2,3]
>>myList.extend(4)
>>myList
[1,2,3,4,5,6]
BUT throws an error if used on a single element
>>myList = [1,2,3]
>>myList.extend(4)
Type Error: 'int' object is not iterable
To extend a single element requires you to make a 1-item list: myList.extend([4])
More info/examples:
http://www.tutorialspoint.com/python/list_extend.htm
More on the differences:
append vs. extend
I am writing a piece of code the this is the scenario I am facing.
How to update the list which is in for-condition, and for the next iteration, the list in for-condition is updated?
Eg.,
list = [0,1,2]
for i in list:
print list[i]
if list[i] == 0:
list.append(3)
The entry '3' should get updated in the list in for-condition.
Is it possible to update the list in for-condition dynamically?
Thanks in advance.
Yes, if you do that, it will work. However, it's usually not a good idea, because it can create confusing interactions between the iteration and the loop-body action. In your example, you add an element at the end, but if, for instance, you change an element in the middle, you may or may not see the change depending on where you are in the list when it happens. (For instance, you could change the value of an element you already iterated past.)
Also, you shouldn't name a variable list, as that shadows the built-in type called list.
Be aware that your loop is incorrect, in Python this snippet:
for e in lst:
… Iterates over each element e in lst, and e is not an index, it's an element - so all the parts in the question where you wrote list[i] are incorrect, they should have been simply i. Try this solution instead, it's equivalent and less error prone:
lst = [0, 1, 2]
print(lst)
lst += [3] * lst.count(0) # add as many 3s at the end as there are 0s in the list
Notice that it's never a good idea to modify a list at the same time you're traversing it. Also, don't use list as a variable name, there's a built-in function with that name.
This is my code
[temp.append(i.get_hot_post(3)) for i in node_list]
[hot_posts+i.sort(key=sort_by_rate) for i in temp ]
get_hot_posts() return a list of 3 items this way
return recent_posts[0:amount-1]
it could be that the list is shorter than 3 elements and it probably mess the things around but go on
[temp.append(i.get_hot_post(3)) for i in node_list]
after this command, in "temp" i have a list of lists and it's fine.
But when it executes
[hot_posts+i.sort(key=sort_by_rate) for i in temp ]
it gives this error
TypeError: can only concatenate list (not "NoneType") to list
List method sort returns None (just changing list). You can use sorted() function instead.
PS.
[temp.append(i.get_hot_post(3)) for i in node_list]
is not very good idea, cause you will have a list of None. Possible variants:
temp += [i.get_hot_post(3) for i in node_list]
or even
from operator import methodcaller
temp += map(methodcaller(get_hot_post, 3), node_list)
I think you meant sorted(i), no? i.sort() does the sorting in-place and returns nothing.
Also, why would you like to do [hot_posts + ...]? This will not store the values in the hot_posts, so the operation is meaningless, unless you assign the result to a new variable.
I suspect you wanted to do something like
temp = [i.get_hot_post(3) for i in node_list]
hot_posts = [sorted(i, key=sort_by_rate) for i in temp]
Although I have no idea what your last line is supposed to do. Now it just sorts each of these small lists of three and that's it.