I've started teaching myself Python, and as an exercise I've set myself the task of generating lookup tables I need for another project.
I need to generate a list of 256 elements in which each element is the value of math.sin(2*i*pi/256). The problem is, I don't know how to generate a list initialized to "dummy" values that I can then use a for loop to step through and assign the values of the sin function.
Using list() seems to create an "empty" list, but with no elements so I get a "list assignment index out of range" error in the loop. Is there a way to this other than explicitly creating a list declaration containing 256 elements all with "0" as a value?
Two answers have already shown you how to build your list at a single stroke, using the "list comprehension" (AKA "listcomp") construct.
To answer your specific question, though,
mylist = [None] * 256
is the simplest way to make a list with 256 items, all None, in case you want to fill it in later.
If you start with an empty list, call its .append(...) method to add each item at the end. A loop doing nothing but append on an initially-empty list is what normally gets replaced with a more concise listcomp.
Of course, for the task you actually state,
mylist = [math.sin(2 * math.pi/256)] * 256
would be by far the best approach -- no sense computing a sin 256 times when the argument's always the same (daringly assuming that what you say is what you mean;-).
my_list = [math.sin(2 * math.pi/256) for i in xrange(256)]
You can also try:
l = []
for i in range(256):
l.append(math.sin(2*math.pi/256))
This is an iterative for loop that keeps adding the same value to the end of the list 256 times
I need to generate a list of 256
elements in which each element is the
value of math.sin(2*math.pi/256)
To answer your question literally:
my_list=[math.sin(2*math.pi/256)]*256
Thanks for the help, everyone. I did make a mistake in the specification I posted for the question, in that the value of each element in the list needs to be the sin of the angle incremented by 2*pi/256 each time. The code that works for me in that case is:
li = [math.sin((2*math.pi/256)*i) for i in xrange(0,256)]
Related
My question is te following:
I'm new to Python programming and I'm a little confused about the correct use of lists.
When I want for example to create a list of 10 elements I am doing something like:
list = [None for x in range(10)]
And when I have something to put on it, I do:
list[lastPosition] = data
But after some research I noticed that this use for lists is not efficient or recommended. But how other way could a list be inicialized before I have all the data? My idea is to have a list (specially something like Java's Collections) inicialized and as the data comes I fill it.
I hope my question is clear enough.
If you don't know in advance how many elements will be in the list,
then don't try to allocate 10 elements. Start with an empty list and use the append function to append to it:
lst = []
...
lst.append(value)
If for some reason you really need to initialize a list to a constant size,
and the initial elements are immutable values,
then you can do that like this:
lst = [None] * 10
If the initial elements are mutable values,
you most probably don't want to use this technique,
because all the elements will all point to the same instance.
In that case your original technique is mostly fine as it was:
lst = [SomeClass() for _ in range(10)]
Note that I renamed the variable from list to lst,
because list is a built-in class in Python,
and it's better to avoid such overlaps.
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.
previous answers on how to remove None from a list dont help me!
I am creating a list of tuples with:
list(zip(*[iter(pointList)] *3))
So what i have is
[(object1,object2,object3),(object4,object5,object6),(object7,None,None)]
or
[(object1,object2,object3),(object4,object5,object6),(object7,object8,None)]
And i want to remove the None in the tuples (which only can occure at the last entry of the list!). So my desired output would be:
[(object1,object2,object3),(object4,object5,object6),(object7)]
or
[(object1,object2,object3),(object4,object5,object6),(object7,object8)]
What i thought would help me is:
filter(None,myList)
Tuples are immutable so once you construct a tuple you cannot alter its length or set its elements. Your only option is thus to construct new tuples as a post processing step, or don't generate these tuples in the first place.
Post processing
Simply use a generator with the tuple(..) constructor in a list comprehension statement:
[tuple(xi for xi in x if xi is not None) for x in data]
Alter the "packing" algorithm
With packing I mean converting a list of m×n items into n "slices" of m elements (which is what your first code fragment does).
If - like the variable name seems to suggest - pointList is a list. You can save yourself the trouble of using zip, and work with:
[tuple(pointList[i:i+3]) for i in range(0,len(pointList),3)]
directly. This will probably be a bit more efficient as well since here we never generate tuples with Nones in the first place (given postList does not contain Nones of course).
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.
Caveat: this is a straight up question for code-golfing, so I know what I'm asking is bad practise in production
I'm trying to alter an array during a list comprehension, but for some reason it is hanging and I don't know why or how to fix this.
I'm dealing with a list of lists of indeterminite depth and need to condense them to a flat list - for those curious its this question. But at this stage, lets just say I need a flat list of all the elements in the list, and 0 if it is a list.
The normal method is to iterate through the list and if its a list add it to the end, like so:
for o in x:
if type(o)==type([]):x+=o
else:i+=o
print i
I'm trying to shorten this using list comprehension, like so.
print sum([
[o,x.append(o) or 0][type(o)==type([])]
for o in x
]))
Now, I know List.append returns None, so to ensure that I get a numeric value, lazy evaluation says I can do x.append(o) or 0, and since None is "falsy" it will evaulate the second part and the value is 0.
But it doesn't. If I put x.append() into the list comprehension over x, it doesn't break or error, or return an iteration error, it just freezes. Why does append freeze during the list comprehension, but the for loop above works fine?
edit: To keep this question from being deleted, I'm not looking for golfing tips (they are very educational though), I was looking for an answer as to why the code wasn't working as I had written it.
or may be lazy, but list definitions aren't. For each o in x, when the [o,x.append(o) or 0][type(o)==type([])] monstrosity is evaluated, Python has to evaluate [o,x.append(o) or 0], which means evaluating x.append(o) or 0, which means that o will be appended to x regardless of whether it's a list. Thus, you end up with every element of x appended to x, and then they get appended again and again and again and OutOfMemoryError
What about:
y = [element for element in x if type(element) != list or x.extend(element)]
(note that extend will flatten, while append will only add the nested list back to the end, unflattened).