2 回答

TA貢獻1817條經驗 獲得超14個贊
在函數中修改這樣的可變組件不是很好的做法。你是對的,你建議的兩種方法都修改了原始對象。對于像這樣的簡單情況,最好返回一個新對象。
在這個簡單的例子中,正如你所說,你可以復制字典。IMO你應該在函數中執行此操作。您需要從一開始就清楚字典的結構是什么,因為您可能需要一個深度副本。
def my_fun(x, d):
d = d.copy()
for i, el in enumerate(x):
d[el] = i + 1
return d
或者,您可以創建一個新詞典并使用舊詞典進行更新。我更喜歡這個,但你必須小心重復鍵。
def my_func(x, d):
result = {el: i for i, el in enumerate(x)}
result.update(d)
return result
對于更復雜的事情,您可能有一個類來封裝整個事情。
class Foo:
def __init__(self, d):
self.d = d
def update(self, x):
for i, el in enumerate(x):
self.d[el] = i

TA貢獻1921條經驗 獲得超9個贊
您的兩個示例并不等效。它們之所以以這種方式顯示,只是因為您碰巧將函數參數命名為與全局變量相同的名稱。等效函數是:
d = {'a': 0}
def my_fun(x, foo):
for i, el in enumerate(foo):
foo[el] = i + 1
return foo
但這個函數不是“pythonic”。修改傳入的對象是可以的,但是當您這樣做時,也不要返回它。如果在函數中復制對象,則返回它。你所做的只是制造了一個模棱兩可的東西 - 在一個眩光點上,我會從返回聲明中假設原始的字典沒有被修改。至于清晰度,這就是文檔字符串的用途?,F在每個打字的人都知道發生了什么。help(my_fun)
def my_fun(x, foo):
"""Update foo with an enumeration of x"""
for i, el in enumerate(foo):
foo[el] = i + 1
您的第一個示例是最危險的。它對全局對象執行靜默更新。我們盡量避免這種事情。當它完成時,doc字符串和希望函數本身的名稱清楚地表明一些令人討厭的panky正在進行中。
至于復制,這是你可以讓調用者決定的事情。更新傳遞到函數中的字典比復制它更通用,因為調用方可以決定是否應復制正在更新的數據。當然,由于您不再返回更新的對象,因此調用方需要做更多的工作。
d_copy = d.copy()
my_fun(['b', 'c'], d_copy)
這還不錯。代碼很清楚。這并不是說我們用完了換行符或其他東西。
添加回答
舉報