在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
提交
取消
