Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

List comprehension and copies of types

Tags:

I am often tempted not to create a new list when using list comprehensions, because if the list is huge, it would mean more space needed to compute (the way I understand it the list is not bieng aliased int his case, a new memory space is created for the new list)

As an illustrative example (this could be done in one line):

def average_list(lst):
    lst = [x for x in lst if x > 0]
    return np.average(lst)

Is it dangerous to use lst in this way, both in right and left part of the assignment? If so, what situations would cause a problem by reusing lst?

If so why is this "safer"?

def average_list(lst):
    clean_lst = [x for x in lst if x > 0]
    return np.average(clean_lst )
like image 564
dirtyw0lf Avatar asked Jun 26 '18 19:06

dirtyw0lf


People also ask

Does list comprehension make a copy?

5. Using list comprehension. The method of list comprehension can be used to copy all the elements individually from one list to another. This takes around 0.217 seconds to complete.

What is list comprehension method?

List comprehension offers a shorter syntax when you want to create a new list based on the values of an existing list. Example: Based on a list of fruits, you want a new list, containing only the fruits with the letter "a" in the name.

What is list comprehension used for?

List comprehension is an elegant way to define and create lists based on existing lists. List comprehension is generally more compact and faster than normal functions and loops for creating list. However, we should avoid writing very long list comprehensions in one line to ensure that code is user-friendly.

What is the difference between list and list comprehension?

The for loop is a common way to iterate through a list. List comprehension, on the other hand, is a more efficient way to iterate through a list because it requires fewer lines of code. List comprehension requires less computation power than a for loop because it takes up less space and code.


1 Answers

def average_list(lst):
    lst = [x for x in lst if x > 0]
    return np.average(lst)

caller_list = [1,4,-5]
average_list(caller_list)
# caller_list is unchanged

here you're reusing the lst name only in the function, but you're not changing lst in the caller context (and garbage collection doesn't work since the caller still holds a reference on the data)

So reassigning a variable name is perfectly safe but sometimes considered as bad practice because one should not change the values or references of passed arguments.

Note: in the case of list a way to change the data itself (which would surprise your function users so don't do it) would be (only applies to lists & more generally mutable objects)

    lst[:] = [x for x in lst if x > 0]

With this slice assignment, the name isn't reused, the object itself is reused & modified. The original contents of the list is replaced by the new contents, here shrunk as there is less data in the new, filtered version. It's cool on local & global variables, but should be avoided in lists passed as parameters (like append, pop should be avoided too in the general case, always to follow the principle of least astonishment)

like image 194
Jean-François Fabre Avatar answered Sep 28 '22 17:09

Jean-François Fabre