2012-06-07 89 views
2

我想在初始化一個類的某些屬性時禁止進一步的分配。例如;在Person實例'p'初始化後,沒有人可以明確地爲'ssn'(社會安全號碼)屬性賦值。 _ SETATTR _而分配值內_ 初始化 _方法也被稱爲,因此它是不是我想要的。我只想限制進一步的作業。我怎樣才能做到這一點?如何限制在構造函數外設置屬性?

class Person(object): 
    def __init__(self, name, ssn): 
     self.name = name 
     self._ssn = ssn 

    def __setattr__(self, name, value): 
     if name == '_ssn': 
      raise AttributeError('Denied.') 
     else: 
      object.__setattr__(self, name, value) 

>> p = Person('Ozgur', '1234') 
>> AttributeError: Denied. 
+0

只是因爲在'分配__init__'還呼籲'__setattr__' – neoascetic

+0

我想你可能不得不嘗試元類 –

+4

僅供參考,這實際上並不是Python如何工作。記錄您的API以告訴其他開發人員不要更改它。 – detly

回答

8

的常用方法是使用「私有」屬性,開始帶有下劃線,和只讀的公共訪問屬性:

import operator 

class Person(object): 
    def __init__(self, name, ssn): 
     self.name = name 
     self._ssn = ssn 
    ssn = property(operator.attrgetter("_ssn")) 

請注意,這並不能真正阻止任何人改變屬性_ssn,但前導_文檔屬性是私有的。

+2

+1。 Python的哲學是,不是用語言強制的「你不能碰這個」,而是使用以'_'開頭的屬性來表示實現細節 - 這意味着客戶端*可以試圖擺弄它,但是它們不再被覆蓋通過您對後向/前向兼容性或類不變量的任何保證。所以,他們可以搗鼓,他們可以破壞事情,但它自己的錯誤。 – lvc

2

您可以繞過setattr通過直接分配給構造函數中的實例字典。當然,這一招總是可以被用來欺騙你僱用做出_ssn只讀任何其他籃球(在經過最初寫)

class Person(object): 
    def __init__(self, name, ssn):  
     self.name = name 
     self.__dict__['_ssn'] = ssn 

    def __setattr__(self, name, value): 
     if name == '_ssn': 
      raise AttributeError('Denied.') 
     else: 
      object.__setattr__(self, name, value) 
相關問題