2016-03-28 75 views
0

我有兩個類,一個是基類,第二個需要從基類繼承。我的問題與在這種情況下正確使用super()。如何正確使用Super()(Python 2/3)從基類繼承?

當我創建我的類TestService時,它繼承自ServiceMap,所以我在想所需的MRO應該是:TestService - > ServiceMap - > OrderedDict。

這是否意味着我的初始化程序TestService我應該打電話給super(ServiceMap, self).__init__(value=value, kwargs=None)?然後初始化TestService類的其餘部分? (如下所示)。或者我需要在每個繼承的類中從ServiceMap重新創建初始化程序?我真的不想重新創建該代碼,因爲將會有多種類型的服務從類型ServiceMap繼承。

請提供一些super()指導!

感謝

from collections import OrderedDict 
    from sys import version_info 
    from inspect import ismethod 
    import json 
    import six 
    import copy 

    class ServiceMap(OrderedDict): 
     _map = None 
     #---------------------------------------------------------------------- 
     def __init__(self, value=None, **kwargs): 
      """Initializer object""" 
      self._map = OrderedDict() 
      if value: 
       if isinstance(value, dict): 
        for k,v in six.iteritems(value): 
         if isinstance(v, dict): 
          v = ServiceMap(value=v) 
         self._map[k] = v 
         del k,v 
      if kwargs: 
       for k,v in six.iteritems(kwargs): 
        self._map[k] = v 
     #---------------------------------------------------------------------- 
     def items(self): 
      return six.iteritems(self._map) 
     #---------------------------------------------------------------------- 
     def iteritems(self): 
      return six.iteritems(self._map) 
     #---------------------------------------------------------------------- 
     def __iter__(self): 
      return self._map.__iter__() 
     #---------------------------------------------------------------------- 
     def next(self): 
      return self._map.next() 
     #---------------------------------------------------------------------- 
     def __setitem__(self, k, v): 
      self._map[k] = v 
     #---------------------------------------------------------------------- 
     def __getitem__(self, k): 
      if k not in self._map: 
       # if parameter k DNE, create a empty object as ServiceMap 
       self[k] = ServiceMap() 
      return self._map[k] 
     #---------------------------------------------------------------------- 
     def __setattr__(self, k, v): 
      if k == '_map': 
       super(ServiceMap, self).__setattr__(k,v) 
      else: 
       self[k] = v 
     #---------------------------------------------------------------------- 
     def __getattr__(self, k): 
      if k == '_map': 
       super(ServiceMap, self).__getattr__(k) 
      else: 
       return self[k] 
     #---------------------------------------------------------------------- 
     def __delattr__(self, key): 
      return self._map.__delitem__(key) 
     #---------------------------------------------------------------------- 
     def __contains__(self, k): 
      return self._map.__contains__(k) 
     #---------------------------------------------------------------------- 
     def __str__(self): 
      """represents the object as a string""" 
      return json.dumps(self.as_dictionary()) 
     #---------------------------------------------------------------------- 
     def __repr__(self): 
      return str(self) 
     #---------------------------------------------------------------------- 
     def as_dictionary(self): 
      """ 
      recursively iterate the object inorder to conver the ServiceMap object 
      to a traditional dictionary type object.""" 
      vals = {} 
      for k,v in self.items(): 
       if type(v) is ServiceMap: 
        vals[k] = v.as_dictionary() 
       else: 
        vals[k] = v 
       del k,v 
      return vals 
     #---------------------------------------------------------------------- 
     def values(self): 
      return self._map.values() 
     #---------------------------------------------------------------------- 
     def __cmp__(self, value): 
      value = ServiceMap.compare(value) 
      return self._map.__cmp__(value) 
     #---------------------------------------------------------------------- 
     def __eq__(self, value): 
      value = ServiceMap.compare(value) 
      if not isinstance(value, dict): 
       return False 
      return self._map.__eq__(value) 
     #---------------------------------------------------------------------- 
     def __ge__(self, value): 
      value = ServiceMap.compare(value) 
      return self._map.__ge__(value) 
     #---------------------------------------------------------------------- 
     def __gt__(self, value): 
      value = ServiceMap.compare(value) 
      return self._map.__gt__(value) 
     #---------------------------------------------------------------------- 
     def __le__(self, value): 
      value = ServiceMap.compare(value) 
      return self._map.__le__(value) 
     #---------------------------------------------------------------------- 
     def __lt__(self, value): 
      value = ServiceMap.compare(value) 
      return self._map.__lt__(value) 
     #---------------------------------------------------------------------- 
     def __ne__(self, value): 
      value = ServiceMap.compare(value) 
      return self._map.__ne__(value) 
     #---------------------------------------------------------------------- 
     def __delitem__(self, key): 
      return self._map.__delitem__(key) 
     #---------------------------------------------------------------------- 
     def __len__(self): 
      return self._map.__len__() 
     #---------------------------------------------------------------------- 
     def clear(self): 
      self._map.clear() 
     #---------------------------------------------------------------------- 
     def copy(self): 
      return copy.deepcopy(self) 
     #---------------------------------------------------------------------- 
     def get(self, key, default=None): 
      return self._map.get(key, default) 
     #---------------------------------------------------------------------- 
     def has_key(self, key): 
      return key in self._map 
     #---------------------------------------------------------------------- 
     def iterkeys(self): 
      return self._map.iterkeys() 
     #---------------------------------------------------------------------- 
     def itervalues(self): 
      return self._map.itervalues() 
     #---------------------------------------------------------------------- 
     def keys(self): 
      return self._map.keys() 
     #---------------------------------------------------------------------- 
     def pop(self, key, default=None): 
      return self._map.pop(key, default) 
     #---------------------------------------------------------------------- 
     def popitem(self): 
      return self._map.popitem() 
     #---------------------------------------------------------------------- 
     def setdefault(self, key, default=None): 
      self._map.setdefault(key, default) 
     #---------------------------------------------------------------------- 
     def update(self, *args, **kwargs): 
      if len(args) != 0: 
       self._map.update(*args) 
      self._map.update(kwargs) 
     #---------------------------------------------------------------------- 
     def viewitems(self): 
      return self._map.viewitems() 
     #---------------------------------------------------------------------- 
     def viewkeys(self): 
      return self._map.viewkeys() 
     #---------------------------------------------------------------------- 
     def viewvalues(self): 
      return self._map.viewvalues() 
     #---------------------------------------------------------------------- 
     @classmethod 
     def fromkeys(cls, seq, value=None): 
      """ 
      creates a ServiceMap object from a set of keys with default values 
      This allows the creation of template objects. 
      """ 
      val = ServiceMap() 
      val._map = OrderedDict.fromkeys(seq, value) 
      return val 
     #---------------------------------------------------------------------- 
     @classmethod 
     def compare(self, value): 
      if type(value) is ServiceMap: 
       return value._map 
      else: 
       return value 

    class TestService(ServiceMap): 
     _con = None 
     _url = None 
     def __init__(self, url, connection, value=None): 
      super(ServiceMap, self).__init__(value=value) 
      self._url = None 
      self._con = None 
+0

你真的你*試過*你顯示的代碼?有什麼問題?另外,爲什麼你完全重新實現'OrderedDict'只是爲了重定向到'_map'屬性(注意這是* class屬性* - http://stackoverflow.com/q/1680528/3001761)。 – jonrsharpe

+0

@jonrsharpe - 儘管BaseClass應初始化_map對象,但我的self._map始終顯示爲None。 –

+1

然後展示一個[mcve],就這個問題而言,絕大多數你發佈的代碼都是不相關的。 – jonrsharpe

回答

1

簡單的方式與Python 3繼承是

class TestService(ServiceMap): 

    def __init__(self, value=None, **kwargs): 
    super().__init__(value, kwargs) #equivalent to ServiceMap.__init__(self,value, kwargs) 
    code_specific to this class() 

這給你一個「適當」的ServiceMap,然後你可以補充

+2

這是僅Python3。這個問題也被標記爲「python2.7」。 –

0

您需要使用:

class TestService(ServiceMap): 
    def __init__(self, url, connection, value=None): 
     super(TestService, self).__init__(value=value) 

這將調用父類的__init__(),你的情況ServiceMap並創建所需的MRO。

0

super()給出了它的第一個參數,您希望獲得父類的位置。通常,這與您當前定義的類相同,以便您可以獲得當前定義的類的父級方法__init__。在這種情況下,您想使用super(TestService, self)。有時,您將定義TestService的子類,並且您沒有定義方法__init__。這意味着將使用TestService__init__方法。由於TestService明確使用TestServicesuper(),您仍然會得到正確的父項__init__方法。如果您使用self.__class__,這可能是誘人的,那麼該行將進入子類的無限遞歸。

0

在超類中擴展方法時使用super,即要運行超類方法的代碼以及子類中的代碼。

您的示例代碼不正確:您需要調用 super(TestService, self)__ init __ (value=value)來運行超類的__ init __方法,然後您可以繼續初始化子類。

如果您沒有擴展方法,則不需要調用super,只是不要在子類中定義方法,並且超類代碼將運行。

如果您重寫某個方法,請在子類中定義該方法,但不要調用super

在Python3你不需要傳遞參數給super,你可以叫 super().some_method(arg1, arg2)

(編輯以反映Zondo的評論)