为了账号安全,请及时绑定邮箱和手机立即绑定

Python:在函数内向可变对象添加属性

Python:在函数内向可变对象添加属性

九州编程 2022-08-16 18:43:11
我试图了解在这种情况下的最佳实践是什么。假设我们有一个字典(或一个列表或其他可变的),它在函数内部被更改(但在函数外部定义)d = {'a': 0}def my_fun(x):    for i, el in enumerate(x):        d[el] = i + 1打电话,然后打印,这很好。但是,也可以通过向函数添加 return 语句来完成相同的操作(尽管不是必需的)。或者,甚至,return 语句加上函数中表示 dict 的第二个 arg:my_fun(['b', 'c'])print(d){'a':0, 'b':1, 'c':2}d = {'a': 0}def my_fun(x, d):    for i, el in enumerate(x):        d[el] = i + 1    return dreturn 语句和第二个参数在这里都是多余的,我只是发现它们在清晰度方面有所帮助。它更容易阅读。呼叫,然后再次打印d = my_fun(['b', 'c'], d)print(d){'a':0, 'b':1, 'c':2}最后,你可以选择传递可变对象的副本:这可能更pythonic,但我不知道例如,在内存管理方面,制作副本是否是很好的做法。d = my_fun(['b', 'c'], d.copy())这里什么是最佳实践?您如何处理这些类型并向函数内的可变对象添加属性?
查看完整描述

2 回答

?
大话西游666

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


查看完整回答
反对 回复 2022-08-16
?
郎朗坤

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)

这还不错。代码很清楚。这并不是说我们用完了换行符或其他东西。


查看完整回答
反对 回复 2022-08-16
  • 2 回答
  • 0 关注
  • 110 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信