Как заставить дочерний класс использовать родительские значения по умолчанию? - PullRequest
1 голос
/ 24 апреля 2019

У меня есть родительский класс:

class BaseClass:
    def __init__(self, foo, bar=10):
        self.foo = foo  

И унаследованный от него класс:

class InheritedClass(BaseClass):
    def __init__(self, x, y, bar=10):
        super().__init__(True, bar=bar)
        self.x = x
        self.y = y

На данный момент bar имеет значение по умолчанию как в родительском, так и в унаследованном классе, которое я должен отслеживать, чтобы убедиться, что они оба синхронизированы. Как я могу изменить конструктор InheritedClass, чтобы вместо него использовать значение по умолчанию для bar, определенное в BaseClass?


Я пробовал:

class InheritedClass(BaseClass):
    def __init__(self, x, y, bar=None):
        if bar is None:
            super().__init__(True)
        else:
            super().__init__(True,bar)
        self.x = x
        self.y = y

, который обеспечивает поведение, которое я ищу, но не кажется очень масштабируемым. Есть ли лучший способ?

Ответы [ 3 ]

1 голос
/ 24 апреля 2019

Не раскрывайте аргументы родителя вообще в подписи; просто передайте то, что вы получили (если что-нибудь), следующему классу в MRO.

class BaseClass:
    def __init__(self, foo, bar=10, **kwargs):
        super().__init__(**kwargs)
        # Do something with bar
        self.foo = foo


class InheritedClass(BaseClass):
    def __init__(self, x, y, **kwargs)
        kwargs['foo'] = True
        super().__init__(**kwargs)
        self.x = x
        self.y = y

Вы должны в любом случае принять и передать произвольные ключевые слова, чтобы правильно использовать super, поэтому вы можете также сделать то же самое для аргументов родительского класса, даже если вы их уже «знаете».

Это также означает всегда с использованием аргументов ключевых слов для __init__, поскольку вы не можете предсказать, как позиционные аргументы вашего класса будут взаимодействовать с другим классом в MRO. (Позиционные аргументы могут использоваться только по принципу «первым пришел - первым обслужен», и вы просто не знаете, в случае множественного наследования , когда будет вызван метод вашего класса.)

foo = InheritedClass(bar=9, x=3, y=10)
1 голос
/ 24 апреля 2019

Вместо этого вы можете использовать переменные аргументы:

class InheritedClass(BaseClass):
    def __init__(self, x, y, *args, **kwargs):
        super().__init__(True, *args, **kwargs)
        self.x = x
        self.y = y
0 голосов
/ 24 апреля 2019

Ваш подход не плохой, и да, есть лучший способ сделать это, может быть, лучше, чем мой, но вот что я придумаю, надеюсь, это поможет.

Пример:

class BaseClass:
    def __init__(self, foo, bar=10):
        self.foo = foo 
        self.bar = bar 

class InheritedClass(BaseClass):
    def __init__(self, x, y, bar=None):
        super().__init__(True, bar=bar)
        if bar is None: bar = self.bar
        self.x = x
        self.y = y
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...