在将 list/dict 传递给函数时,是否应该始终添加 list.copy() / dict.copy()?
Should you always add list.copy() / dict.copy() when passing a list/dict to a function?
我今天有一个痛苦的经历,我不小心将一个列表传递给了一个函数,并且花了我很长时间来调试。该功能旨在接收列表并创建类似列表的副本。我没有意识到这修改了我原来的列表。
L = [0,0,0,0,0]
def similar_list(a_list):
a_list [0] = a_list[0]+1
return a_list
L_similar = similar_list(L)
print(L)
print(L_similar)
#result shows
#[1, 0, 0, 0, 0]
#[1, 0, 0, 0, 0]
我认为最好的方法是在similar_list函数的第一行,添加a_list = a_list.copy()。有更好的方法吗?我问的是在我对 python 的有限研究中,我不记得在示例代码中经常看到这个。如果您能告诉我这是否是标准做法,我们将不胜感激。 (不过,这似乎是一件很容易出错的事情,当出错时很难注意到..)
您可以使用 L_similar = similar_list(L[:])
而不是使用 L_similar = similar_list(L)
来避免对原始列表进行任何更改。
试试这个:
L = [0,0,0,0,0]
def similar_list(a_list):
a_list [0] = a_list[0]+1
return a_list
L_similar = similar_list(L[:])
print(L)
print(L_similar)
#result shows
#[0, 0, 0, 0, 0]
#[1, 0, 0, 0, 0]
[编辑]:
然而,L[:]
和 L.copy()
两种方法都将 return 列表的浅拷贝。这意味着如果您修改任何嵌套列表元素,更改将反映在两个列表中。考虑以下示例:
L = [1, [2, 3], 4]
L_copy = L.copy()
L[1][0] = 5
print(L)
print(L_copy)
#result shows
#[1, [5, 3], 4]
#[1, [5, 3], 4]
为避免此问题,您应该使用 copy
模块中的 copy.deepcopy()
。
import copy
L = [1, [2, 3], 4]
L_copy = copy.deepcopy(L)
L[1][0] = 5
print(L)
print(L_copy)
#result shows
#[1, [5, 3], 4]
#[1, [2, 3], 4]
这完全取决于 similar_list()
应该做什么。
如果您打算修改原始列表,只需像您看到的那样就地更改它:
def similar_list(a_list):
a_list[0] += 1
如您所见,我没有 return 原始列表。根据 Python's convention,修改输入对象的函数或方法,不要 return 它以避免混淆并更清楚。
如果你打算return一个新的列表,它有很多与不变性相关的优点,你可以复制然后修改:
def similar_list(a_list):
newlist = a_list.copy()
newlist[0] += 1
return newlist
如果您需要复制,这是一种标准做法,但最终由您决定。
对于一些优缺点,您可以参考 Python 在 functional programming 上的官方指南。
我今天有一个痛苦的经历,我不小心将一个列表传递给了一个函数,并且花了我很长时间来调试。该功能旨在接收列表并创建类似列表的副本。我没有意识到这修改了我原来的列表。
L = [0,0,0,0,0]
def similar_list(a_list):
a_list [0] = a_list[0]+1
return a_list
L_similar = similar_list(L)
print(L)
print(L_similar)
#result shows
#[1, 0, 0, 0, 0]
#[1, 0, 0, 0, 0]
我认为最好的方法是在similar_list函数的第一行,添加a_list = a_list.copy()。有更好的方法吗?我问的是在我对 python 的有限研究中,我不记得在示例代码中经常看到这个。如果您能告诉我这是否是标准做法,我们将不胜感激。 (不过,这似乎是一件很容易出错的事情,当出错时很难注意到..)
您可以使用 L_similar = similar_list(L[:])
而不是使用 L_similar = similar_list(L)
来避免对原始列表进行任何更改。
试试这个:
L = [0,0,0,0,0]
def similar_list(a_list):
a_list [0] = a_list[0]+1
return a_list
L_similar = similar_list(L[:])
print(L)
print(L_similar)
#result shows
#[0, 0, 0, 0, 0]
#[1, 0, 0, 0, 0]
[编辑]:
然而,L[:]
和 L.copy()
两种方法都将 return 列表的浅拷贝。这意味着如果您修改任何嵌套列表元素,更改将反映在两个列表中。考虑以下示例:
L = [1, [2, 3], 4]
L_copy = L.copy()
L[1][0] = 5
print(L)
print(L_copy)
#result shows
#[1, [5, 3], 4]
#[1, [5, 3], 4]
为避免此问题,您应该使用 copy
模块中的 copy.deepcopy()
。
import copy
L = [1, [2, 3], 4]
L_copy = copy.deepcopy(L)
L[1][0] = 5
print(L)
print(L_copy)
#result shows
#[1, [5, 3], 4]
#[1, [2, 3], 4]
这完全取决于 similar_list()
应该做什么。
如果您打算修改原始列表,只需像您看到的那样就地更改它:
def similar_list(a_list):
a_list[0] += 1
如您所见,我没有 return 原始列表。根据 Python's convention,修改输入对象的函数或方法,不要 return 它以避免混淆并更清楚。
如果你打算return一个新的列表,它有很多与不变性相关的优点,你可以复制然后修改:
def similar_list(a_list):
newlist = a_list.copy()
newlist[0] += 1
return newlist
如果您需要复制,这是一种标准做法,但最终由您决定。
对于一些优缺点,您可以参考 Python 在 functional programming 上的官方指南。