Reputation: 4102
I have two classes, one a base class and the second needs to inherit from the base class. My issue with with the proper use of super() in this case.
When I create my class TestService
, it inherits from ServiceMap
, so I was thinking the desired MRO should be: TestService -> ServiceMap -> OrderedDict.
Would this mean in my initializer of TestService
I should call super(ServiceMap, self).__init__(value=value, kwargs=None)
? Then initialize the rest of the TestService class? (Shown below). Or do I need to re-create the initializer from ServiceMap
in every inherited class? I really don't want to re-create that code since there will be multiple types of Services inheriting from type ServiceMap
.
Please provide some super() guidance!
Thanks
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
Upvotes: 0
Views: 364
Reputation: 367
The simple way to inherit with Python 3 is
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()
This gives you a "proper" ServiceMap that you then complement
Upvotes: 1
Reputation: 55600
Use super
when you are extending a method in a superclass, that is you want to run the superclass's method's code as well as that in the child class.
Your example code is not correct: you need to call
super(TestService, self)__ init __ (value=value)
to run the __ init __ method of the superclass, then you can continue to initialise the child class.
If you are not extending a method, there's no need for a super
call, just don't define the method in the child class and the superclass code will run.
If you are overriding a method, define the method in the subclass but don't call super
.
In Python3 you don't need to pass arguments to super
, you can just call
super().some_method(arg1, arg2)
(Edited to reflect Zondo's comment)
Upvotes: 0
Reputation: 20336
super()
is given for its first argument the point at which you would like to get the parent class. Usually, that's the same class as the one you are currently defining, so that you will get the __init__
method of the parent of the class you are currently defining. In this case, you want to use super(TestService, self)
. Sometimes, you'll define a subclass of TestService
and you don't define the __init__
method. That means that the TestService
__init__
method will be used. Since TestService
explicitly used TestService
for super()
, you will still be getting the correct parent __init__
method. If you used self.__class__
, which may be tempting, that line will go into infinite recursion for a subclass.
Upvotes: 0
Reputation: 85432
You need to use:
class TestService(ServiceMap):
def __init__(self, url, connection, value=None):
super(TestService, self).__init__(value=value)
This calls the __init__()
of the parent class, in your case ServiceMap
and creates the desired mro.
Upvotes: 0