1

I'm trying to make some modifications to the seaborn.JointGrid class. My plan was to make a child class and inherit most methods from the JointGrid class, like so:

import seaborn

class CustomJointGrid(seaborn.JointGrid):

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

If I do this, I do not have access to the variables size, ratio, space etc., which are part of the __init__ method of JointGrid:

def __init__(self, x, y, data=None, size=6, ratio=5, space=.2,
dropna=True, xlim=None, ylim=None) 

I noticed that these variables are not initialized in JointGrid class with the usual self.size = size in the __init__ method. Perhaps this is why I can not access them from my child class?

How can I access these variables size, ratio, space etc?

ekhumoro
  • 115,249
  • 20
  • 229
  • 336
Roald
  • 2,459
  • 16
  • 43
  • Those values are in `args` and `kwargs`. See: https://stackoverflow.com/questions/3394835/args-and-kwargs – Stephen Rauch May 06 '18 at 19:59
  • @StephenRauch Is that true? When I do a `print(kwargs.items())` and `print(*args)` it just shows the arguments with which I called `CustomJointGrid`, not the 'default' arguments which I do not pass. So if I say `CustomJointGrid("x data", "y data", data=data)`, the variable `size` is not available. – Roald May 06 '18 at 20:03
  • The default args are in the source you are inheriting from. Not sure I understand the sticking point. – Stephen Rauch May 06 '18 at 20:05
  • @StephenRauch But how do I access them? For example if I want to change [`f = plt.figure(figsize=(size, size))`](https://github.com/mwaskom/seaborn/blob/102cf08f9e40ef7037daf4b3b60b94ee144dc5cb/seaborn/axisgrid.py#L1653) into something like this in my custom child class: `f = plt.figure(figsize=(size, 2 * size))` it says `AttributeError: 'CustomJointGrid' object has no attribute 'size'` – Roald May 06 '18 at 20:09
  • If you want to be something specific, then set them to whatever you want when you call `super().__init__()`. – Stephen Rauch May 06 '18 at 20:10
  • 1
    @StephenRauch Not sure if I understand. You mean add `size` to `super().init(size=5, *args, **kwargs)`? – Roald May 06 '18 at 20:13
  • `kwargs['size']=5` would be preferred if the user of your class might specify size and you want to override. – Stephen Rauch May 06 '18 at 20:15

2 Answers2

3

You can use inspect.getfullargspec to do this:

>>> import seaborn, inspect
>>> spec = inspect.getfullargspec(seaborn.JointGrid.__init__)
>>> defaults = spec.kwonlydefaults or {}
>>> defaults.update(zip(spec.args[-len(spec.defaults):], spec.defaults))
>>> defaults
{'data': None, 'size': 6, 'ratio': 5, 'space': 0.2, 'dropna': True, 'xlim': None, 'ylim': None}

Note that your code would only need to do this once, since the signature of the imported class won't change.

ekhumoro
  • 115,249
  • 20
  • 229
  • 336
1

Why don't you just use the same arguments as the class you want to subclass?

import seaborn

class CustomJointGrid(seaborn.JointGrid):

    def __init__(self, x, y, data=None, size=6, ratio=5, space=.2,
                 dropna=True, xlim=None, ylim=None, **kwargs):
        super().__init__(x, y, data=data, size=size, ratio=ratio, space=space,
                         dropna=dropna, xlim=xlim, ylim=ylim)

Else you could set some default yourself,

class CustomJointGrid(seaborn.JointGrid):

    def __init__(self, *args, **kwargs):
        size = kwargs.get("size", 6)
        kwargs.update(size=size)
        super().__init__(*args, **kwargs)
        # use size here
        self.someattribute = size*100
ImportanceOfBeingErnest
  • 321,279
  • 53
  • 665
  • 712
  • I thought it would be better and easier to inherit them from the parent class? – Roald May 06 '18 at 20:16
  • Depends. I don't know what you're ultimatively want to achieve. But I updated the answer with a different option. – ImportanceOfBeingErnest May 06 '18 at 20:21
  • Thanks. I want to use the same `size`, ` ratio` etc. as defined in the parent class. The problem with the second answer is that the default option (6) of `size` if not available (`size` is not in `kwargs`), and thus it sets `size=10`. – Roald May 06 '18 at 20:29
  • In that case I think I don't understand the problem. I though you wanted to change the size? But you could of course also set it to `6`. – ImportanceOfBeingErnest May 06 '18 at 20:34
  • No I don't want to change it. I just need to use it in my custom class. For example if I want to change the line in the parent class: `f = plt.figure(figsize=(size, size))` into something like this in my custom child class: `f = plt.figure(figsize=(size, 2 * size))`. – Roald May 06 '18 at 20:37
  • 1
    You cannot change that single line of the parent class. Either you rewrite the complete `__init__` method and use your custom line there, or you initialize the FacetGrid as it is, and later do something like `self.fig.set_size_inches( ... )`. Knowing that the size of the figure is `size`, you can do something like `w,h=self.fig.get_size_inches(); fig.set_size_inches(w, 2*h)`. – ImportanceOfBeingErnest May 06 '18 at 21:29