0

I'm trying to wrap my head around how to utilize inheritance in some code I'm writing for an API. I have the following parent class which holds a bunch of common variables that I'd like to instantiate once, and inherit with other classes to make my code look cleaner:

class ApiCommon(object):
    def __init__(self, _apikey, _serviceid=None, _vclversion=None,
                 _aclname=None, _aclid=None):
        self.BaseApiUrl = "https://api.fastly.com"
        self.APIKey = _apikey
        self.headers = {'Fastly-Key': self.APIKey}
        self.ServiceID = _serviceid
        self.VCLVersion = _vclversion
        self.ACLName = _aclname
        self.ACLid = _aclid
        self.Data = None
        self.IP = None
        self.CIDR = None
        self.fullurl = None
        self.r = None
        self.jsonresp = None
        self.ACLcomment = None
        self.ACLentryid = None

And I am inheriting it in another class below, like so in a lib file called lib/security.py:

from apicommon import ApiCommon

class EdgeAclControl(ApiCommon):
    def __init__(self):
        super(EdgeAclControl, self).__init__()

    ...
    def somemethodhere(self):
        return 'stuff'

When I instantiate an object for ApiCommon(object), I can't access the methods in EdgeAclControl(ApiCommon). Example of what I'm trying which isn't working:

from lib import security

gza = security.ApiCommon(_aclname='pytest', _apikey='mykey',
                        _serviceid='stuffhere', _vclversion=5)

gza.somemethodhere()

How would I instantiate ApiCommon and have access to the methods in EdgeAclControl?

5
  • 2
    That's not how it works. You must instantiate EdgeAclControl instead. Commented Jan 8, 2018 at 23:28
  • 1
    That is "backwards inheritance" which fails to get the methods you need. Commented Jan 8, 2018 at 23:29
  • Okay, so I wouldn't be able to pass arguments to populate variable values that are in ApiControl tho. i.e gza = security.EdgeAclControl(_aclname='pytest', _apikey='stuff', _serviceid='stuff', _vclversion=5) I dont have access to _apikey etc Commented Jan 8, 2018 at 23:30
  • So basically you dont pass arguments to the parent class ever is kind of what I'm understanding? I.e. if i wanted to populate self.APIKey I would have to just assign it inside of the object. i.e. a.APIKey='blah' ? Commented Jan 8, 2018 at 23:33
  • Reread kindall: You must instantiate EdgeAclControl instead. EdgeAclControl is also an ApiCommon. Use EdgeAclControl to specialise (extend/override) the parent class. The child will have access to the parent class methods and attributes. Not the contrary, unless you decide to keep references in it for its own childs. Commented Jan 8, 2018 at 23:41

2 Answers 2

2

Your current code appears to be trying to use inheritance backwards. When you create an instance of ApiCommon, it will only get the methods defined in that base class. If you want to get methods from a subclass, you need to create an instance of the subclass instead.

So the first fix you need to make is to change gza = security.ApiCommon(...) to gza = EdgeAclControl(...) (though depending on how you're doing your imports, you might need to prefix the class name with a module).

The second issue is that your EdgeAclControl class doesn't take the arguments that its base class needs. Your current code doesn't pass any arguments to super(...).__init__, which doesn't work since the _apikey parameter is required. You could repeat all the arguments again in the subclass, but a lot of the time it's easier to use variable-argument syntax instead.

I suggest that you change EdgeAclControl.__init__ to accept *args and/or **kwargs and pass on those variable arguments when it calls its parent's __init__ method using super. That would look like this:

def __init__(self, *args, **kwargs):
    super(EdgeAclControl, self).__init__(*args, **kwargs)

Note that if, as in this example, you're not doing anything other than calling the parent __init__ method in the derived __init__ method, you could get the same effect by just deleting the derived version entirely!

It's likely that your real code does something in EdgeAclControl.__init__, so you may need to keep it in some form. Note that it can take arguments normally in addition to the *args and **kwargs. Just remember to pass on the extra arguments, if necessary, when calling the base class.

Sign up to request clarification or add additional context in comments.

3 Comments

Bam! This is exactly what I was looking for. adding *args, **kwargs* into those init's 100% is what I needed. Thank you so much!!
This is going to be a game changer for me for sure in how I write code. I am very new to inheritance, so thank you!
in reference to your comment Note that if, as in this example, you're not doing anything other than calling the parent __init__ method in the derived __init__ method, you could get the same effect by just deleting the derived version entirely!, I see where you're getting at, but I'd like this parent class to be useful for other classes I will write down the road, so this solves what I'm looking to do.
0

May I ask why you have to instantiate an ApiCommon object? I don't see any point of doing so.

If you insist doing that, you have to add methods in superclass and then subclass may override theses methods. But you still couldn't access methods of EdgeAclControl from ApiCommon object

1 Comment

Because I am a newb with inheritance and oop. Lol

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.