在Python中,我们可以使用@property装饰器来管理对属性的访问。例如,如果我们定义类:class C: def __init__(self,value): self._x = value @property def x(self): """I'm the 'x' property.""" return self._x我们可以获取x的值,但不能更改它:c = C(1)#c.x = 4 # <= this would raise an AttributeError: can't set attribute但是,如果属性是可变类型(例如列表),则可以为属性的位置设置不同的值:c = C([0,0])c.x[0] = 1 # <= this works有办法预防吗?如果x是一个列表,我只想使用类C的方法来更改x的位置值。
1 回答
慕尼黑5688855
TA贡献1848条经验 获得超2个赞
一种方法是返回属性的副本,而不是列表本身。
>>> class C:
... def __init__(self, value):
... self._x = value
... @property
... def x(self):
... return self._x[:]
...
>>> c = C([1, 2, 3])
>>> c.x
[1, 2, 3]
>>> c.x.append(5)
>>> c.x
[1, 2, 3]
>>> c.x[0] = 6
>>> c.x
[1, 2, 3]
或者,该属性可以返回迭代器over属性或视图(例如dict.items()而不是dict)。如果属性很大,则返回迭代器或视图可能有助于限制内存使用,并且与现代Python内置函数和类型的行为更加一致。
如果可变属性本身包含可变属性(例如,列表或字典的列表),则可能也有必要返回这些对象的副本。如果对象图很深,则在时间和资源上可能会很昂贵。有关自定义对象复制方式的方法,请参阅复制模块的文档。
此技术通常用于防止别名问题-其他对象持有对您对象内部状态的引用。
这确实意味着副本可能与real属性不同步,但是如果您的代码设计良好,则其他类无论如何都不应保留您的类的值。
添加回答
举报
0/150
提交
取消