2016-04-21 91 views
0

是顯示我正在處理的API的繼承的兩個類。所以我希望基類ServiceTemplateTest爲所有服務擁有一組共同的屬性,使其表現得像OrderedDict對象一樣。所以基類從OrderedDict入手。然後,我在__init__中執行super()以清除MRO問題。現在當我真正使用這個基類時,當我嘗試從基類中分類__init()時,我遇到了問題。根據我的調試器,它說我需要調用:self._ServiceTemplateTest__init(),但是不應該因爲我調用super()而只是__init()?什麼是正確的方式讓我繼承而不必進行此調用:self._ServiceTemplateTest__init()使用super()(Python)時的繼承問題

我是否需要在非基類上創建一個__init__(),我有多個super()調用?如果是這樣,什麼超級班應該先來?

感謝您提供任何建議!

from collections import OrderedDict 
import urllib2, json, urllib 
class ServiceTemplateTest(OrderedDict): 
    _con = None 
    _url = None 
    def __init__(self, url, connection=None, initialize=False, **kwargs): 
     super(ServiceTemplateTest, self).__init__() 
     self._url = url 
     self._con = connection 
     if initialize: 
      self.__init(connection) 
    def __init(self, connection=None): 
     if connection is None: 
      connection = self._con 
     attributes = [attr for attr in dir(self) 
         if not attr.startswith('__') and \ 
         not attr.startswith('_')] 
     params = {"f":"json"} 
     params = urllib.urlencode(params) 
     result = json.loads(
      urllib2.urlopen(url="{url}?{params}".format(url=self._url, 
                 params=params)).read()) 

     for k,v in result.items(): 
      if k in attributes: 
       setattr(self, "_"+ k, v) 
       self[k] = v 
      else: 
       self[k] = v 
     self.__dict__.update(result) 
    #---------------------------------------------------------------------- 
    @property 
    def connection(self): 
     return self._con 
    #---------------------------------------------------------------------- 
    @connection.setter 
    def connection(self, value): 
     self._con = value 
     self.refresh() 
    #---------------------------------------------------------------------- 
    @property 
    def url(self): 
     return self._url 
    #---------------------------------------------------------------------- 
    @url.setter 
    def url(self, value): 
     """""" 
     self._url = value 
     self.refresh() 
    #---------------------------------------------------------------------- 
    def __str__(self): 
     return json.dumps(self) 
    #---------------------------------------------------------------------- 
    def __repr__(self): 
     return self.__str__() 
    #---------------------------------------------------------------------- 
    def refresh(self): 
     self.__init() 

class SchematicService(ServiceTemplateTest): 
    """schematic service""" 
    _con = None 
    _json_dict = None 
    _json = None 
    _url = None 
    _nbSchematicLayers = None 
    _nbTemplates = None 
    _type = None 
    _name = None 
    _nbEstimatedDiagrams = None 
    def __init__(self, url, connection=None, initialize=False, **kwargs): 
     super(SchematicService, self).__init__(url=url, connection=connection, 
               initialize=initialize, **kwargs) 
     self._url = url 
     self._con = connection 
     if initialize: 
      self.__init(connection) 
    #---------------------------------------------------------------------- 
    @property 
    def nbSchematicLayers(self): 
     if self._nbSchematicLayers is None: 
      self.__init() 
     return self._nbSchematicLayers 
    #---------------------------------------------------------------------- 
    @property 
    def nbTemplates (self): 
     if self._nbTemplates is None: 
      self.__init() 
     return self._nbTemplates 
    #---------------------------------------------------------------------- 
    @property 
    def type(self): 
     if self._type is None: 
      self.__init() 
     return self._type 
    #---------------------------------------------------------------------- 
    @property 
    def name(self): 
     if self._name is None: 
      self.__init() 
     return self._name 
    #---------------------------------------------------------------------- 
    @property 
    def nbEstimatedDiagrams(self): 
     if self._nbEstimatedDiagrams is None: 
      self.__init() 
     return self._nbEstimatedDiagrams 
    @property 
    def somerandompropertytest(self): 
     return "hi" 
if __name__ == "__main__": 
    url = "http://servicesbeta6.esri.com/arcgis/rest/services/S1_Schematics/MapServer" 
    s = SchematicService(url=url, initialize=True) 
    print s 

回答

2

問題不在於繼承或super(),但你試圖從外部類所謂的「私人」的方法。任何名稱以兩個下劃線開頭的方法 - 在這種情況下您的__init() - 對於它們定義的類是私有的。

Python在您可能熟悉的方面並不真正具有「私有」其他面嚮對象語言,而不是它做一些叫做name mangling的東西,使它不方便,而不是不可能。從本質上講,如果你命名一個像__init()這樣的方法,Python會將它轉換爲名爲_NameOfClass__init()的方法,並且在具有相同命名的調用(或訪問屬性)中也會這樣做。訣竅是,「NameOfClass」部分始終是您訪問方法的類的名稱,從 - 子類SchematicService,就您的情況而言。由於名稱不匹配,Python無法找到該方法。

當然,在Python中沒有其他的東西真的是私人的。如果需要,可以通過自己改名來訪問私有方法。然而,傳統的看法通常不是使用雙下劃線私有方法或屬性。按照慣例,如果你想在一個基類上有一個方法,這個方法不應該被從基類外部調用(例如,因爲它不是你想支持的公共API的一部分),所以只需要命名一個方法領先的下劃線。 Pythonistas知道這意味着,「這種方法或屬性的簽名,目的或存在可能會在以後消失,我不應該依賴它」。如果你打算將方法從任何地方調用 - 無論是在子類還是其他不相關的代碼中 - 使它成爲常規的公共方法(名稱中沒有前導下劃線);如果您只希望它可以被子類訪問,請使用單個前導下劃線。

+0

謝謝,這是非常有幫助的。我總是學到新東西! –

+0

通過更改名稱,像魅力一樣工作。欣賞它。 –

1

dcrosta已經從一個子類中調用__init這個問題已經回答了(主要是我將要發佈的相同的東西)。我只是想在你的代碼示例中補充一點,整個SchematicService.__init__()只是沒用,因爲它只會重做ServiceTemplateTest.__init__()已經完成的工作。

此外,同時使類名和實例屬性具有相同的名稱不會有助於Wrt /可讀性/可維護性。如果這些屬性默認爲尚未設置的實例屬性,最好將它們設置爲__init__()中的實例屬性。

+0

你能舉一個例子來解釋你最後的陳述嗎? –