2016-10-04 1 views
-1

Что опрятное и самый вещий способ решить эту проблему:Pythonic superclass с конструктором classmethod: переопределить, наследовать, ...?

Учитывая класс с @classmethod конструктору, например, в образце коды 1. Но теперь подкласс с двумя классами, которые оба требуют совершенно иной дополнительного аргумента, например, в образце кода 2. Если это необходимо решить, используя *args, **kwargs (образец 3)? Или я не должен наследовать @classmethod, а скопировать его в каждом классе? Или создать суперкласс def read_csv и обратиться к подклассам @classmethod?

Подкласс очень важен, поскольку в классах существуют другие сложные функции.

Другие люди, работающие с этим кодом, должны понимать, какие аргументы должны проходить при инициализации различных классов.

Пример кода 1

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 

Пример кода 2

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') 

Пример кода 3

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 
+0

«Самый аккуратный и самый пифонический путь» выглядит как мнение, основанное на мне. Также у вас уже есть рабочее решение, и оно достаточно аккуратное и достаточно питово. Если вы считаете, что что-то не так в вашем решении и ищете способы его улучшения, вы можете переформулировать вопрос, по крайней мере, будет реальная проблема. – Goyo

ответ

1

Я думаю, вы могли бы избежать определений новых подклассаподклассов вообще) каждый раз, когда у вас есть новый атрибут для Car класса пути создания атрибутов каждого экземпляра из kwargs переданных __init__ метода класса:

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]) 

Тогда вы могли бы сделать:

ferrari = Car.from_csv('some.csv', name='ferrari', ferrari_logo='logo.jpg') 
fiat = Car.from_csv('fiat.csv', name='fiat', fiat_wheels=8) 

Update:

Тогда вы можете подклассифицировать выше, если вам нужно определить отдельные методы на уровне подкласса. Вам не нужно писать отдельный __init__ для каждого подкласса.

+0

Спасибо за ваш ответ. Подклассификация требуется, так как есть и другие функции в этих классах. Я сделал свой пример немного слишком простым (обновлено) –

+1

@LaurensKoppenol О, тогда вы можете подклассифицировать это решение. Тогда вам не понадобится '__init__' для каждого подкласса. На уровне подкласса будут определены только требуемые методы. –

+0

Это рабочее решение, но не позволяет моим коллегам легко работать с моими классами, так как не видно, какие ** kwargs подклассов необходимы/необязательны и не отображаются документы __init__ подкласса –