Python 类,为什么我要 return getters 中的 obj 副本?

Python classes, why should I return a copy of obj in getters?

我了解到我们使用getter和setter来防止用户直接修改class的数据属性。但是为什么我们必须 return 在 getter 中复制或不可变对象?如果 return 是可变的,用户可以改变这些变量吗?

    def get_encryption_dict(self):
        '''
        Used to safely access a copy self.encryption_dict outside of the class
        
        Returns: a COPY of self.encryption_dict
        '''
        return self.encryption_dict.copy()

是的,您需要在 python 中小心(与在其他语言中一样),因为某些对象是可变的。最重要和常见的情况是集合类型,例如 listdict.

例如,如果您示例中的代码是这个代码,那么它会返回对字典的可变引用!

return self.encryption_dict   # WARNING, do not do that at home / in your own class code, mutable reference returned, oyu probably don't want it!

return self.some_other_internal_list  # same warning!

But why do we have to return a copy or immutable object in getter? Can a user mutate those variables if the returns are mutable?

是的!例如,在返回的 dict 上调用 .clear() 将清除对象使用的内部字典...糟糕...

您可以像代码示例中那样轻松复制可枚举列表或字典:使用 .copy()get a (shallow) copy 所有字典,[:] 用于列表。

return self.encryption_dict.copy()   # much less risk here, the internal dictionary from the object can't be modified, it's a (shallow) copy returned.

return self.some_other_internal_list[:]   # Ok as well, the '[:]' actually creates a copy of a list.

如评论中所述,请注意,如果对象是可变的,您获得列表的正确副本仍然会暴露对同一对象的引用,这可能是意外的。 (这就是为什么我们称这些为“浅”副本,与“深”副本相对)。

根据经验,追求不变性将保护您免受细微(或不太细微)错误的侵害。