Можно ли использовать *args в классе данных?

Недавно я начал использовать классы данных, и они станут хорошим дополнением к версии 3.7. Мне любопытно, возможно ли воссоздать ту же функциональность этого класса, используя классы данных.

class Nav(object):
    def __init__(self, name:str, menu, page, *submenus):
        self.name = name
        self.menu = menu
        self.page = page
        self.submenus = submenus

foo = Nav("name", "menu", "page")

Это не работает. Вызывает исключение TypeError: __init__() missing 1 required positional argument: 'submenus'

@dataclass
class Nav(object):
    name:str
    menu: Any
    page: Any
    submenus: tuple

foo = Nav("name", "menu", "page")

Я предполагаю, что это связано с тем, что у класса нет инструкций для распаковки аргументов. Есть ли способ указать декоратору класса данных, что подменю необходимо распаковать?


person Marcel Wilson    schedule 08.06.2018    source источник
comment
Python3.7 сейчас нестабилен. Может это просто баг?   -  person Sraw    schedule 08.06.2018
comment
Непопулярное мнение: не следует использовать varargs. Просто используйте список.   -  person Aran-Fey    schedule 08.06.2018
comment
@JaredSmith Я добавил лучший пример того, как это не работает.   -  person Marcel Wilson    schedule 08.06.2018
comment
Кстати, при вводе кортежей, если вы не знаете конкретный тип и длину или не делаете неизменяемость частью контракта API, я бы вместо этого использовал Iterable. Я бы тоже использовал это вместо List.   -  person Jared Smith    schedule 08.06.2018
comment
@ Аран-Фей, у меня была похожая мысль; просто передайте фактический кортеж.   -  person Marcel Wilson    schedule 08.06.2018
comment
[непроверенная идея]попробуйте вручную распаковать в post-init[/непроверенная идея]   -  person cmc    schedule 27.05.2019


Ответы (1)


Я вижу в PEP пример того, как переопределить __init__.

Иногда сгенерированного метода init недостаточно. Например, предположим, что вы хотите иметь объект для хранения *args и **kwargs:

@dataclass(init=False)
class ArgHolder:
    args: List[Any]
    kwargs: Mapping[Any, Any]

    def __init__(self, *args, **kwargs):
        self.args = args
        self.kwargs = kwargs

a = ArgHolder(1, 2, three=3)
person Marcel Wilson    schedule 08.06.2018
comment
Мои мысли точно. Декоратор дает вам хороший __repr__, но да, я немного разочарован. - person Marcel Wilson; 08.06.2018
comment
Год спустя, и я должен забрать свой комментарий. Рэймонд Хеттингер выступил на PyCon 2018 с докладом о том, почему класс данных по-прежнему довольно хорош (даже если нам придется переопределить init) youtube.com/watch?v=T-TwcmT6Rcw - person Marcel Wilson; 20.06.2019