2016-03-28 4 views
0

Ich habe zwei Klassen, eine eine Basisklasse und die zweite muss von der Basisklasse erben. Mein Problem mit der richtigen Verwendung von super() in diesem Fall.Wie erben ich ordnungsgemäß von einer Basisklasse mit Super() (Python 2/3)?

Wenn ich meine Klasse TestService erstelle, erbt von ServiceMap, so dachte ich, die gewünschte MRO sollte sein: TestService -> ServiceMap -> OrderedDict.

Würde dies in meinem Initialisierer von TestService bedeuten, ich sollte super(ServiceMap, self).__init__(value=value, kwargs=None) anrufen? Dann initialisiere den Rest der TestService-Klasse? (Unten gezeigt). Oder muss ich den Initialisierer aus ServiceMap in jeder geerbten Klasse neu erstellen? Ich möchte diesen Code wirklich nicht neu erstellen, da es mehrere Typen von Services geben wird, die vom Typ ServiceMap erben.

Bitte geben Sie einige super() Anleitung!

Dank

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

Haben Sie tatsächlich ly * versuchte * den Code, den du zeigst? Was ist das Problem? Warum implementieren Sie das 'OrderedDict' vollständig neu, nur um zum' _map' Attribut umzuleiten (beachten Sie, dass dies ein * Klassenattribut * ist - http://Stackoverflow.com/q/1680528/3001761). – jonrsharpe

+0

@jonrsharpe - Meine self._map wird immer als None angezeigt, obwohl die BaseClass das _map Objekt initialisieren sollte. –

+1

Dann zeigen Sie eine [mcve] davon, die überwiegende Mehrheit des Codes, die Sie geschrieben haben, ist irrelevant, soweit es diese Frage betrifft. – jonrsharpe

Antwort

1

Der einfache Weg, mit Python erben 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() 

Dies gibt Ihnen eine "richtige" ServiceMap, die Sie dann ergänzen

+2

Dies ist nur Python3. Die Frage wird auch mit 'python2.7' markiert. –

0

Sie müssen verwenden:

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

Das die __init__() der Elternklasse nennt, in Ihrem Fall ServiceMap und schafft die gewünschte MRO.

0

super() wird für das erste Argument der Punkt angegeben, an dem Sie die Elternklasse erhalten möchten. Normalerweise entspricht dies der Klasse, die Sie gerade definieren, sodass Sie die Methode __init__ des übergeordneten Elements der Klasse erhalten, die Sie gerade definieren. In diesem Fall möchten Sie super(TestService, self) verwenden. Manchmal definieren Sie eine Unterklasse von TestService, und Sie definieren nicht die __init__ Methode. Das bedeutet, dass die TestService__init__ Methode verwendet wird. Da TestService explizit TestService für super() verwendet wird, erhalten Sie immer noch die richtige Eltern __init__ Methode. Wenn Sie self.__class__ verwendet haben, was verlockend sein könnte, wird diese Zeile für eine Unterklasse in unendliche Rekursion gehen.

0

Verwenden Sie super, wenn Sie eine Methode in einer Oberklasse erweitern, dh Sie möchten den Code der Oberklassenmethode genauso wie den in der Kindklasse ausführen.

Ihr Beispielcode ist nicht korrekt: Sie müssen super(TestService, self)__ init __ (value=value) aufrufen, um die Methode __ init __ der übergeordneten Klasse auszuführen. Anschließend können Sie die untergeordnete Klasse weiter initialisieren.

Wenn Sie eine Methode nicht erweitern, brauchen Sie keinen super Aufruf, definieren Sie einfach nicht die Methode in der Kindklasse und der Superklassencode wird ausgeführt. Wenn Sie eine Methode überschreiben, definieren Sie die Methode in der Unterklasse, aber rufen Sie nicht super auf.

In Python3 Sie brauchen keine Argumente super zu übergeben, können Sie einfach anrufen super().some_method(arg1, arg2)

(Edited Zondo Kommentar zu reflektieren)

Verwandte Themen