Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I simply pass arguments to parent constructor in child class?

Tags:

python

I want to design some derived classes in Python but don't know how to make it very simple without too much effort and code.

Let me explain, I have the following class:

class Page(object):
  def __init__(self, name):
    self.name = name

I want to derive some children:

class PageWithImage(Page):
  def __init__(self, name, image):
    # Need I do this boring code? - how to replace it?
    super(PageWithImage, self).__init__(name = name)
    self.image = image

How can I skip rewriting the whole list of variables for the call to the super method like name = name? (since there can be a lot of such variables)

How can I make it more readable? (less code is often more readable)

I do not like the code I wrote - since auto-completion doesn't work with this code:

class PageWithImage(Page):
  def __init__(self, *args, **kwrds):
    # Need I do this boring code? - how to replace it?
    super(PageWithImage, self).__init__(*args, **kwrds)
    self.image = image
like image 782
Chameleon Avatar asked Feb 08 '15 20:02

Chameleon


2 Answers

I think that your code is quite broken or untested (bad indentation, bad syntax), because it won't run currently, maybe you should edit.

But if you want to simplify your "super call" :

class PageWithImage(Page):
    def __init__(self, *args, **kwargs):
        super(PageWithImage, self).__init__(*args, **kwargs)

It will takes all arguments and keywords arguments (remove the **kwargs if you don't need keywords arguments).

Yes, less code is often more readable, but it's not always the case, list comprehensions, complicated functions using *args and **kwargs, lambda, etc... can be obscure sometimes for a developer even if they save +20 characters.

So, if the number of parameters can be easily ~10, you should try to re-design or stuff them into a dictionnary, or a list, depending on the nature of these parameters.

like image 63
Raito Avatar answered Oct 21 '22 12:10

Raito


There's no way to extend an argument list at the end in a easy way. If you want to do that, you pretty much need to write out all the arguments each time.

You can however extend the arguments at the start:

class Base(object):
    def __init__(self, base_arg0, base_arg1, base_arg2):
        pass

class Derived(Base):
    def __init__(self, derived_arg, *args):
        super().__init__(*args)

You'd call this with something like Derived(da, ba0, ba1, ba2) (note that the derived arg comes before the base args).

In Python 3, you can also specify keyword-only arguments, by putting a bare * in the argument list:

class BaseKW(object):
    def __init__(self, *, base_arg):
        pass

class DerivedKW(BaseKW):
    def __init__(self, *, derived_arg, **kwargs):
        super().__init__(**kwargs)

You could call this with either DerivedKW(derived_arg=da, base_arg=ba) or DerivedKW(base_arg=ba, derived_arg=da) (the order of the keyword arguments in the call does not matter).

like image 30
Blckknght Avatar answered Oct 21 '22 13:10

Blckknght