2015-11-02 103 views
2

我試圖將一些模塊包裝到類中,並開始玩屬性。在Python中創建一個類實例屬性只讀

將這兩個答案組合在一起:making instance attribute read-onlyvalidating attributes

我希望能夠創造DataFolder類的一個實例:

df = DataFolder(owner="me", path="/.data") 

之後,我希望能夠允許編輯owner屬性,但不是path屬性。我希望能夠驗證初始化時刻的屬性(pathowner)以及之後(但僅owner)。

class DataFolder(object): 
    _path = None 

    #---------------------------------------------------------------------- 
    def __init__(self,owner,path): 
     self.path = path 
     self.owner = owner 

    @property 
    #---------------------------------------------------------------------- 
    def owner(self): 
     return self._owner 

    @owner.setter 
    #---------------------------------------------------------------------- 
    def owner(self,owner_value): 
     if "me" not in owner_value: 
      raise Exception("invalid owner") 
     self._owner = owner_value 

    @property 
    #---------------------------------------------------------------------- 
    def path(self): 
     return self._path 

    @path.setter 
    #---------------------------------------------------------------------- 
    def path(self,path_value): 
     if self._path is not None: 
      raise AttributeError("Cannot edit path of existing data folder") 
     if "dat" not in path_value: 
      raise Exception("invalid folder") 
     self._path = path_value 

它是正確的/最好使用全局變量_path = None@path.setter檢查if self._path is not None:代碼工作正常,但我想知道是否有更好的方法。

+0

這似乎是一個合理的方式做到這一點 - 這是一個*類屬性*,不是*全局變量*。儘管如此,我會提出一個'ValueError'而不是基於'Exception'作爲無效參數。由於這看起來是有效的代碼,你可能會更好[codereview.se]。 – jonrsharpe

+0

謝謝!將使用ValueError來代替。它在私有變量前面的「_」變得混亂,但我希望習慣它們:) –

回答

0

它看起來很好,除了一件事:_path = None屬於一類。

這只是一個小的改良效果:

class DataFolder(object): 
    def __init__(self, owner, path): 
     self._path = None # now it is an instance variable. 
     self.path = path 
     self.owner = owner 

    @property 
    def owner(self): 
     return self._owner 

    def _validate_owner(self, owner_value): 
     if "me" not in owner_value: 
      raise ValueError("invalid owner") 

    @owner.setter 
    def owner(self, owner_value): 
     self._validate_owner(owner_value) 
     self._owner = owner_value 

    @property 
    def path(self): 
     return self._path 

    def _validate_path(self, path_value): 
     if self._path is not None: 
      raise AttributeError("Cannot edit path of existing data folder") 
     if "dat" not in path_value: 
      raise ValueError("invalid folder") 

    @path.setter 
    def path(self, path_value): 
     self._validate_path(path_value) 
     self._path = path_value 

使用:

d = DataFolder('me', 'data') 
print(d.path, d.owner) 
d.path = 'new_data' 

輸出:

('data', 'me') 
new_me 
AttributeError: Cannot edit path of existing data folder 
+1

你能概述你認爲這樣更好嗎?爲什麼不從'__init__'委託給getter,而不是複製代碼?你爲什麼要訪問類的驗證,而不是實例(這會影響後面的繼承)? – jonrsharpe

+0

@jonrsharpe,相當合理。更新。 – sobolevn

+0

但是這不具有OP原始代碼的行爲,即您可以只設置其中一個屬性一次... – jonrsharpe

相關問題