Aesthetic way of appending to a list in Python?

Question:

When appending longer statements to a list, I feel append becomes awkward to read. I would like a method that would work for dynamic list creation (i.e. don’t need to initialize with zeros first, etc.), but I cannot seem to come up with another way of doing what I want.

Example:

import math
mylist = list()
phi = [1,2,3,4] # lets pretend this is of unknown/varying lengths
i, num, radius = 0, 4, 6

while i < num:
    mylist.append(2*math.pi*radius*math.cos(phi[i]))
    i = i + 1

Though append works just fine, I feel it is less clear than:

mylist[i] = 2*math.pi*radius*math.cos(phi[i])

But this does not work, as that element does not exist in the list yet, yielding:

IndexError: list assignment index out of range

I could just assign the resulting value to temporary variable, and append that, but that seems ugly and inefficient.

Asked By: ryanjdillon

||

Answers:

You don;t need an existing list and append to it later. Just use list comprehension

List comprehension,

  • is fast,
  • easy to comprehend,
  • and can easily be ported as a generator expression

    >>> import math
    >>> phi = [1,2,3,4]
    >>> i, num, radius = 0, 4, 6
    >>> circum = 2*math.pi*radius
    >>> mylist = [circum * math.cos(p) for p in phi]
    

Reviewing your code, here are some generic suggestions

  • Do not compute a known constant in an iteration

    while i < num:
        mylist.append(2*math.pi*radius*math.cos(phi[i]))
        i = i + 1
    

should be written as

circum = 2*math.pi
while i < num:
    mylist.append(circum*math.cos(phi[i]))
    i = i + 1
  • Instead of while use for-each construct

    for p in phi:
        mylist.append(circum*math.cos(p))
    
  • If an expression is not readable, break it into multiple statements, after all readability counts in Python.

Answered By: Abhijit

In this particular case you could use a list comprehension:

mylist = [2*math.pi*radius*math.cos(phi[i]) for i in range(num)]

Or, if you’re doing this sort of computations a lot, you could move away from using lists and use NumPy instead:

In [78]: import numpy as np

In [79]: phi = np.array([1, 2, 3, 4])

In [80]: radius = 6

In [81]: 2 * np.pi * radius * np.cos(phi)
Out[81]: array([ 20.36891706, -15.68836613, -37.32183785, -24.64178397])

I find this last version to be the most aesthetically pleasing of all. For longer phi it will also be more performant than using lists.

Answered By: NPE
mylist += [2*math.pi*radius*math.cos(phi[i])]
Answered By: mihaicc

you can use list concatenation, but append is twice as fast according to this:

import math
mylist = list()
phi = [1,2,3,4] # lets pretend this is of unknown/varying lengths
i, num, radius = 0, 4, 6

while i < num:
    mylist += [(2*math.pi*radius*math.cos(phi[i]))]
    i = i + 1
Answered By: zenpoy
Categories: questions Tags: , , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.