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”。修改传入的对象是可以的,但是当您这样做时,也不要返回它。如果在函数中复制对象,则返回它。你所做的只是制造了一个模棱两可的东西 - 在一个眩光点上,我会从返回声明中假设原始的字典没有被修改。至于清晰度,这就是文档字符串的用途。现在每个打字的人都知道发生了什么。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)
这还不错。代码很清楚。这并不是说我们用完了换行符或其他东西。
添加回答
举报