Pythonic superclass with classmethod constructor: override, inherit, ...?
<p>What is the neatest and most pythonic way to solve this:</p>

<p>Given a class with a <code>@classmethod</code> constructor such as in code sample 1. But now subclass it with two classes which both require a totally different additional argument, such as in code sample 2. Should this be solved by using <code>*args, **kwargs</code> (sample 3)? Or should I not inherit the <code>@classmethod</code> but rather copy it in every class? Or create a superclass <code>def read_csv</code> and refer from the subclasses' <code>@classmethod</code>? </p>

<p>Subclassing is essential as there are other complex functions in the classes.</p>

<p>Other people working with this code should understand what arguments to pass when initializing the various classes.</p>

<p><strong>Code sample 1</strong></p>

<pre><code>class Car(object):
    @classmethod
    def from_csv(cls, csv):
       df = pd.read_csv(csv)
       # could be more complex
       return cls(df)

    def __init__(self, df):
        self.df = df
</code></pre>

<p><strong>Code sample 2</strong></p>

<pre><code>class Ferrari(Car):
    def __init__(self, df, ferrari_logo):
        self.df = df
        self.ferrari_logo = ferrari_logo

    def somethingcomplex(self):
        #complex ferrari method

def Fiat(Car):
    def __init__(self, df, fiat_wheels):
        self.df = df
        self.fiat_wheels = fiat_wheels

    def somethingcomplex(self):
        #complex fiat method

Fiat.from_csv('fiat.csv', fiat_wheels=8)
Ferrari.from_csv('ferrari.csv', ferrari_logo='logo.jpg')
</code></pre>

<p><strong>Code sample 3</strong></p>

<pre><code>class Car(object):
    @classmethod
    def from_csv(cls, csv, *args, **kwargs):
       df = pd.read_csv(csv)
       # could be more complex
       return cls(df, *args, **kwargs)

    def __init__(self, df):
        self.df = df
</code></pre>

<p>I think you could avoid defining a new <em>subclass</em> (and <em>subclassing</em> altogether) each time you have a new attribute for the <code>Car</code> class by setting up the attributes of each instance from the <code>kwargs</code> passed to the <code>__init__</code> method of the class:</p>

<pre><code>class Car(object):
    @classmethod
    def from_csv(cls, csv, **kwargs):
        df = pd.read_csv(csv)
        # could be more complex
        return cls(df, **kwargs)

    def __init__(self, df=None, **kwargs):
        self.df = df
        for kw in kwargs:
            setattr(self, kw, kwargs[kw])
</code></pre>

<p>Then you could do:</p>

<pre><code>ferrari = Car.from_csv('some.csv', name='ferrari', ferrari_logo='logo.jpg')
fiat = Car.from_csv('fiat.csv', name='fiat', fiat_wheels=8)
</code></pre>

<p><strong>Update:</strong></p>

<p>Then you could subclass the above if you need to define separate methods at the subclass level. You wont need to write a separate <code>__init__</code> for each subclass. </p>

python inheritance class-method