2 回答

TA貢獻1873條經(jīng)驗 獲得超9個贊
歸根結(jié)底,您無法保護您的對象免受檢查和操縱。另外,總是問自己“究竟來自誰?” 當您想“保護”數(shù)據(jù)時。
有時,圍繞不閱讀文檔的用戶編寫代碼是不值得的。
話雖如此,你可以考慮return tuple(self.__x)
在吸氣劑中。另一方面,如果__x
包含其他可變對象,則不會阻止用戶操作這些內(nèi)部對象。(return list(self.__x)
也將返回數(shù)據(jù)的淺拷貝,但隱含的“嘿,我應(yīng)該是不可變的!”信號。)
您絕對應(yīng)該考慮的是在方法中更改self.__x = xx
為,以便用戶執(zhí)行self.__x = list(xx)
__init__
var = [] c = C(var)
不能“輕松”(或錯誤地,同樣,可能存在可變的內(nèi)部對象)c
通過 mutating改變 的狀態(tài)var
。

TA貢獻1851條經(jīng)驗 獲得超3個贊
最簡單的方法是接受一個可迭代對象__init__并在內(nèi)部將其轉(zhuǎn)換為元組:
class C(object):
def __init__(self, iterable):
self._tuple = tuple(iterable)
@property
def x(self):
return self._tuple
@x.setter
def x(self, value):
raise RuntimeError('can\'t reset the x attribute.')
c = C([1, 2, 3])
# c.x = 'a' Will raise 'RuntimeError: can't reset the x attribute.'
print(c.x)
像這樣的設(shè)計使從類實例化的任何對象都是不可變的,因此變異操作應(yīng)該返回新對象而不是更改當前對象的狀態(tài)。
例如,假設(shè)您要實現(xiàn)一個函數(shù),該函數(shù)使 中的每個項目遞增 1 self.x。使用這種方法,您需要編寫類似于以下內(nèi)容的內(nèi)容:
def increment_by_one(c):
return C(t+1 for t in c.x)
由于創(chuàng)建和銷毀對象會產(chǎn)生相關(guān)成本x,因此應(yīng)根據(jù)您的用例評估此方法(防止屬性突變)與 @timgeb 建議的方法之間的權(quán)衡。
添加回答
舉報