通过子类化修改命名元组的构造函数参数?

Posted

技术标签:

【中文标题】通过子类化修改命名元组的构造函数参数?【英文标题】:Modifying a namedtuple's constructor arguments via subclassing? 【发布时间】:2011-03-29 07:06:50 【问题描述】:

我想创建一个namedtuple,它代表一个短位域中的各个标志。我正在尝试对其进行子类化,以便在创建元组之前解压缩位域。但是,我目前的尝试不起作用:

class Status(collections.namedtuple("Status", "started checking start_after_check checked error paused queued loaded")):
    __slots__ = ()

    def __new__(cls, status):
        super(cls).__new__(cls, status & 1, status & 2, status & 4, status & 8, status & 16, status & 32, status & 64, status & 128)

现在,我对super() 的经验是有限的,而我对__new__ 的经验几乎不存在,所以我不太确定如何理解(对我而言)神秘错误TypeError: super.__new__(Status): Status is not a subtype of super。谷歌搜索和挖掘文档并没有产生任何启发性。

帮助?

【问题讨论】:

【参考方案1】:

你差一点就完成了 :-) 只有两个小更正:

    new 方法需要一个return 语句 super 调用应该有两个参数,clsStatus

生成的代码如下所示:

import collections

class Status(collections.namedtuple("Status", "started checking start_after_check checked error paused queued loaded")):
    __slots__ = ()

    def __new__(cls, status):
        return super(cls, Status).__new__(cls, status & 1, status & 2, status & 4, status & 8, status & 16, status & 32, status & 64, status & 128)

它运行干净,就像你所期望的那样:

>>> print Status(47)
Status(started=1, checking=2, start_after_check=4, checked=8, error=0, paused=32, queued=0, loaded=0)

【讨论】:

应该是super(Status, cls)!【参考方案2】:

我会避免使用super,除非您明确支持多重继承(希望这里不是这种情况;-)。只需执行类似...:

def __new__(cls, status):
    return cls.__bases__[0].__new__(cls,
                                    status & 1, status & 2, status & 4,
                                    status & 8, status & 16, status & 32,
                                    status & 64, status & 128)

【讨论】:

你也可以使用这个来减少代码重复:return cls.__bases__[0].__new__(cls, *(status & (1 << x) for x in range(0, 8)))

以上是关于通过子类化修改命名元组的构造函数参数?的主要内容,如果未能解决你的问题,请参考以下文章

python学习--为元组中每个元素命名

EffectiveJava

Python不可变对象元组(tuple)详解

子类化集合命名元组

当参数是构造函数的参数声明类型的子类时,反射找不到构造函数

Flutter 6种构造函数详解