Каков предпочтительный способ определения (не относящихся к делу) параметров при переопределении методов? - PullRequest
1 голос
/ 11 марта 2020

Предположим, этот код:

class A:
    def foo(self, bar, baz=None, *args, **kwargs):
        ... # Do some stuff with using bar, baz, args and kwargs
        return result


class B(A):
    def foo(self, *args, **kwargs):
        ... # Not using bar or baz
        return super().foo(*args, **kwargs)


class C(A):
    def foo(self, bar, baz=None, *args, **kwargs):
        ... # Not using bar or baz
        return super().foo(bar, baz, *args, **kwargs)

Как видите, есть 2 способа переопределения foo. Класс C явно указывает аргументы, а класс B просто добавляет их в *args и *kwargs. Оба работают нормально. Я подумал, что если бы я использовал baz и bar, я бы явно указал их, поскольку они улучшают читабельность и экономят мне словарь / список вызовов. Но в случае, если я не использую их, я думаю, что обернуть их в *args и **kwargs должно быть хорошо. Есть ли какой-либо предпочтительный способ сделать это и какое-либо обоснование?

1 Ответ

2 голосов
/ 11 марта 2020

Вы получили это. Если вы не используете bar / baz, не принимайте их, просто передайте их как часть args / kwargs, не разбираясь с ними самостоятельно.

A Полуофициальная рекомендация (см. раздел «Практические советы»), особенно в более сложных сценариях наследования ios, заключается в том, чтобы вообще не принимать *args (за исключением случаев, когда вам действительно нужно принимать переменные позиционные аргументы, а скорее чем лень не указывать известное фиксированное число аргументов, требуемое вашими родителями), и пусть каждый слой принимает только:

  1. Аргументы, которые они используют, и
  2. Аргументы произвольных ключевых слов (**kwargs)

Причина этого заключается в том, что:

  1. Позиционные аргументы могут изменять позицию при изменении иерархии
  2. Это становится невероятно уродливым окончательный порядок позиционных аргументов, когда задействовано множественное наследование (или, что еще хуже, алмазное наследование)

Требуется передать все аргументы по ключевому слову: l Это на медленнее, но это тривиально в накладных расходах на много вызовов через super() диспетчеризацию, и очень ясно, какие аргументы передаются и не передаются. Поэтому для своего кода вы просто должны сделать:

class A:
    def foo(self, bar, baz=None, **kwargs):
        ... # Do some stuff with using bar, baz, and kwargs
        return result

class B(A):
    def foo(self, **kwargs):
        ... # Not using bar or baz
        return super().foo(**kwargs)

class C(A):
    # ... same as B aside from omitted code

с вызывающими абонентами, звонящими по номеру:

instance.foo(bar=1)
instance.foo(bar=2, baz=3)

или т.п.

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