Python как добавить __init__ параметр в подкласс - PullRequest
0 голосов
/ 30 октября 2018

У меня есть подкласс, разделяющий __ init __ его базового класса:

class SubClass(BaseClass)
    def __init__(self, param, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.thing = param

Проблема, с которой я столкнулся, заключается в том, что подкласс __ init __ параметр "param" передается в super().__init__(*args, **kwargs) в качестве дополнительного параметра. Это обычно дает мне ошибку вроде:

TypeError: __init__() takes from 1 to 2 positional arguments but 3 were given

Я не хочу этого. Я только хочу, чтобы "param" использовался для этих экземпляров подкласса. Как прекратить отправку дополнительного параметра в базовый класс __ init __, сохраняя возможность использовать его в подклассе __ init __? Пример кода для воспроизведения проблемы:

from unittest import TestCase


class TestCaseSubClass(TestCase):

    def __init__(self, param, *args, **kwargs):
        super().__init__(*args, **kwargs)  # Just use whatever is in TestCase's init + our stuff
        self.thing = param
        print(self.thing)


class TestClass(TestCaseSubClass(param='bdfbdfb')):

        def test_stuff(self):
            print('test stuff here')

Или с просто сырым питоном, без импорта, почему я не могу это сделать? (та же ошибка)

class A(object):
    def __init__(self, athing='thing'):
        self.thing = athing
        print(self.thing)

class AB(A):
    def __init__(self, param, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.param= param
        print(self.param)


class ABC(AB(param='thh')):
    pass

ABCinstance = ABC()

1 Ответ

0 голосов
/ 30 октября 2018

Я интерпретирую этот вопрос как «как я могу предоставить параметр по умолчанию для подкласса без определения для него __init__?». Один из возможных способов - определить значение по умолчанию как атрибут класса, к которому вы обращаетесь в родительском классе '__init__:

from unittest import TestCase

class TestCaseSubClass(TestCase):
    _default_param = None
    def __init__(self, *args, **kwargs):
        param = kwargs.pop("param", self._default_param)
        super().__init__(*args, **kwargs)  # Just use whatever is in TestCase's init + our stuff
        self.thing = param

class TestClass(TestCaseSubClass):
    _default_param = "bdfbdfb"
    def test_stuff(self):
        print('test stuff here')

x = TestClass()
print(x.thing) #"bdfbdfb"
y = TestClass(param="foo")
print(y.thing) #"foo"

Этот подход не вполне соответствует формату аргумента в вашем вопросе, поскольку теперь param является аргументом только для ключевого слова, а не именованным позиционным аргументом. Принципиальное практическое отличие состоит в том, что вы не можете предоставить аргумент для param, если не ссылаетесь на него по имени: z = TestClass("foo") не сделает этого, например.


Основываясь на изменениях и комментариях к этому вопросу, другая возможная интерпретация может быть следующей: «Как я могу предоставить параметр подклассу, который передается родительскому классу любыми необходимыми средствами?», Который не имеет требований относительно значений по умолчанию , Если вы хотите сделать param обязательный параметр, то вам просто нужно передать значение при создании экземпляра TestClass:

from unittest import TestCase

class TestCaseSubClass(TestCase):
    def __init__(self, param, *args, **kwargs):
        super().__init__(*args, **kwargs)  # Just use whatever is in TestCase's init + our stuff
        self.thing = param

class TestClass(TestCaseSubClass):
    def test_stuff(self):
        print('test stuff here')

x = TestClass("bdfbdfb")
print(x.thing) #"bdfbdfb"
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...