通过子类化修改namedtuple构造函数参数?

21 投票
2 回答
8258 浏览
提问于 2025-04-16 02:44

我想创建一个 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 是什么意思。我在网上搜索和查阅文档也没有找到有用的信息。

有人能帮忙吗?

2 个回答

10

我建议你不要使用 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)
20

你差不多就对了 :-) 只需要做两个小修改:

  1. new 方法需要加一个 return 语句
  2. 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)

撰写回答