能否在数据类中使用 *args 呢?

24

我最近开始使用dataclasses,它们将成为3.7中的一个不错的新功能。我想知道是否有可能以及如何使用dataclasses重新创建具有相同功能的类。

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__()缺少1个必需的位置参数:"submenus"

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

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

我认为这是因为类没有指令来解包参数。 有没有办法告诉dataclass装饰器需要解包子菜单?


Python3.7现在不太稳定。也许这只是一个bug? - Sraw
5
不受欢迎的观点:这不是可变参数应该使用的方式。只需使用列表。 - Aran-Fey
@JaredSmith,我添加了一个更好的例子来说明它不起作用。 - Marcel Wilson
顺便提一下,当输入元组时,除非您知道具体类型和长度或将不可变性作为API合同的一部分,否则我会使用Iterable。我也会使用它来代替List - Jared Smith
@Aran-Fey 我也有类似的想法;只需传入一个实际元组即可。 - Marcel Wilson
1
【未经测试的想法】尝试在 post-init 中手动解包。【未经测试的想法】 - cmc
1个回答

16

我在PEP中看到了如何覆盖__init__的示例。

Sometimes the generated init method does not suffice. For example, suppose you wanted to have an object to store *args and **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)

3
我的想法完全一样。装饰器为您提供了一个漂亮的__repr__,但是是的,我有点失望。 - Marcel Wilson
3
一年后,我不得不收回我的评论。Raymond Hettinger在PyCon 2018上发表了一篇演讲,介绍了数据类仍然非常棒的原因(即使我们需要覆盖__init__方法)。https://www.youtube.com/watch?v=T-TwcmT6Rcw - Marcel Wilson
看起来,如果你使用这个,就不能使用frozen=True。真是太可惜了! - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接