列表理解和类型的副本

dir*_*0lf 5 python memory list-comprehension

我经常试图在使用列表推导时不要创建新的列表,因为如果列表很大,则意味着需要更多的空间来计算(我理解它的方式列表不是别名的,他的情况下,新的内存空间是为新列表创建的)

作为一个说明性的例子(这可以在一行中完成):

def average_list(lst):
    lst = [x for x in lst if x > 0]
    return np.average(lst)
Run Code Online (Sandbox Code Playgroud)

以这种方式使用lst是危险的,无论是在作业的左右两部分?如果是这样,通过重复使用lst会导致什么情况?

如果是这样,为什么这会"更安全"?

def average_list(lst):
    clean_lst = [x for x in lst if x > 0]
    return np.average(clean_lst )
Run Code Online (Sandbox Code Playgroud)

Jea*_*bre 3

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
Run Code Online (Sandbox Code Playgroud)

在这里,您仅在函数中重用lst名称,但在调用者上下文中没有更改lst(并且垃圾收集不起作用,因为调用者仍然保留对数据的引用)

因此,重新分配变量名是完全安全的,但有时被认为是一种不好的做法,因为不应该更改传递参数的值或引用。

注意:如果有list一种方法可以更改数据本身(这会让您的函数用户感到惊讶,所以不要这样做)(仅适用于列表和更普遍的可变对象)

    lst[:] = [x for x in lst if x > 0]
Run Code Online (Sandbox Code Playgroud)

通过此切片分配,名称不会被重用,对象本身会被重用和修改。列表的原始内容被新内容替换,此处缩小,因为新的过滤版本中的数据较少。它在局部和全局变量上很酷,但在作为参数传递的列表中应该避免(例如appendpop在一般情况下也应该避免,始终遵循最小惊讶的原则)