Вопрос по python-3.x, python – Почему `object .__ init__` не принимает аргументов

1

Почему нетobject.__init__ принимать*args, **kwargs в качестве аргументов? Насколько я вижу, это ломает некоторый простой код очень раздражающим способом без каких-либо преимуществ:

Скажем, мы хотим убедиться, что все__init__называются все родительские классы. Пока каждый init следует простому соглашению вызоваsuper().__init__ это гарантирует, что вся иерархия будет пройдена и будет выполнена ровно один раз (также без необходимости указывать родителя). Проблема возникает, когда мы передаем аргументы:

class Foo:
    def __init__(self, *args, **kwargs):
        print("foo-init")
        super().__init__(*args, **kwargs) # error if there are arguments!

class Bar:
    def __init__(self, *args, **kwargs):
        print("bar-init")
        super().__init__(*args, **kwargs)

class Baz(Bar, Foo):
    def __init__(self, *args, **kwargs):
        print("baz-init")
        super().__init__(*args, **kwargs)

b1 = Baz() # works
b2 = Baz("error")

Каковы причины этого и каков лучший обходной путь (! Он легко решаем в моем конкретном случае, но который зависит от дополнительных знаний об иерархии)? Лучшее, что я могу видеть, это проверить, является ли родитель объектом, и в этом случае не выдавать ему никаких аргументов ... ужасно ужасно.

Обычно вы должны знать, кто является родителем, а не просто передавать произвольные аргументы. jadkik94
@jadkik Для того, кто нарушает «СУХОЙ» и не обязательно, если я пишу миксин. Но да, во многих случаях существует простой обходной путь, и МИ в любом случае не является хорошей идеей. Так что да, меня больше интересуют причины этого, но если бы было хорошее общее решение, это все равно было бы интересно. Voo
@ sr2222 Ожидается ли его использование в произвольной иерархии наследования? Да. Наследование - это часто используемое решение (состав работает достаточно часто), и ситуации, в которых вы ожидаете «произвольно» иерархии наследования с MI еще более редки. Так что нет проблем для 99,9% всех классов, но дляobject как базовый класс каждого объекта? Да, я ожидаю, что справлюсь с этим. Voo
Поэтому теперь нам нужно пометить классы как «предназначенные для использования для наследования». или нет? Вы просто создаете сложность и добавляете специальное поведение в случае, если только разработчики не будут ленивыми при наследовании от класса. Silas Ray
По этой логике, КАЖДОЙ__init__() метод в каждом классе, который кто-либо пишет в Python, должен быть*args а также**kwargsдаже если их просто выбросить. Что не имеет большого смысла. И еще труднее понять, что делать с именованными аргументами (нужно ли добавлять их кargs и / илиkwargs прежде чем передать их вверх по цепочке? Просто уронить их?) Это тоже ломает OO, так как тогда все параметры для__init__() из n-го подкласса в конечном итоге в__init__() родителя без какого-либо контроля. Silas Ray

Ваш Ответ

2   ответа
3

Рэймонд Хеттингерсупер () считается супер есть некоторая информация о том, как справиться с этим. Он находится в разделе «Практические советы».

4

Ты можешь видетьhttp://bugs.python.org/issue1683368 для обсуждения. Обратите внимание, что кто-то там на самом делеasked для того, чтобы вызвать ошибку. Также смобсуждение Python-Dev.

В любом случае, ваш дизайн довольно странный. Почему вы пишете каждый класс, чтобы взять неуказанный*args а также**kwargs? В общем случае лучше, чтобы методы принимали аргументы, в которых они нуждаются. Принятие открытых аргументов для всего может привести к всевозможным ошибкам, если кто-то, например, неправильно наберет имя ключевого слова. Иногда это необходимо, но это не должно быть способом действий по умолчанию.

Я пишу миксин, поэтому обычно не знаю своего родителя. Теперь я мог простоnot Вызовите super из моего смешанного кода и ожидайте, что реальный объект явно вызовет родительский конструктор, но это кажется подверженным ошибкам и избыточным. Но спасибо за сообщение об ошибке, я его прочту :) Voo

Похожие вопросы