2011-03-16 34 views
2

這個@property decorator的使用適合獲得一個很好的實例字段封裝嗎?我試圖實現Foobar類的客戶端不能以任何方式爲foobar實例的字段vel指定任意值,事實上繞過屬性設置器方法中定義的賦值規則。在Python中封裝實例字段的方式

謝謝。

class Foobar(object): 
    def __init__(self): 
     self._vel = 0 

    @property 
    def vel(self): 
     return self._vel 

    @vel.setter 
    def vel(self, v): 
     self._vel = v if v > 0 else 0 

該領域似乎封裝良好。

>>> foobar = Foobar() 
>>> foobar.vel 
0 
>>> foobar.vel = -1 
>>> foobar.vel 
0 
>>> foobar.vel = 1 
>>> foobar.vel 
1 
+2

呵呵,有沒有問題? – nosklo 2011-03-16 19:10:21

+0

好點,固定。 – Paolo 2011-03-16 19:17:02

+1

請注意,提高ValueError可能是更好的做法,而不是靜默地限制值,這可能會造成混淆。我肯定會這樣做,如果檢查離散值(例如枚舉類型或字符串格式檢查);對於速度我不確定。 – 2011-03-16 19:33:50

回答

4

你不能阻止用戶繞過python中的任何東西。總是有一種方法可以修改/反映/檢查屬性;沒有對象沙盒支持。

在您的例子:

>>> foobar._vel = -1 

將完全繞過財產,直接分配到真正的屬性。你根本無法阻止它。有辦法讓它更難,但用戶可以分配,如果她真的想要,所以有什麼意義?

通常的做法似乎是依靠事實庫的用戶都是成年人並且信任他們:

聲明文件中預期值的範圍,並要求用戶遵循。如果他們不這是他們的錯。

+0

你嚴重誤解了「我們都是成年人」的原則。這並不意味着「我們都很完美」。你不能阻止人們繞過你的API並分配給'foobar._vel',但在你的* public *方法('foobar.vel')上使用訪問器來執行值檢查是完全正常的。不要只是在文檔中提到的東西,並試圖通過責備,因爲你的代碼沒有做任何值檢查。 – 2011-03-16 19:31:36

+2

@Glenn Maynard:我不知道你在哪裏得到這樣的印象,但似乎你違背了大多數現有的python庫 - 很難在真實的知名度中看到屬性級別的那種類型的值檢查python庫。在一般情況下,花費很多時間(屬性中的賦值使用函數調用,並且比屬性賦值慢幾個數量級),因此沒有收益。如果給出了錯誤的值,代碼將失敗,因此檢查確實沒有那麼有用 – nosklo 2011-03-16 20:26:27

+0

人們似乎使用「我們都是成年人」作爲任何事情的藉口。對值進行完整性檢查是完全合理的,就像你無法構造日期(月= 13)一樣。假設「代碼將會失敗」,但是在實踐中,它可能會在稍後產生一個無效的結果,或導致細微的,難以追蹤的錯誤。 (這不是關於優化的問題。) – 2011-03-16 21:11:32