当前位置: 首页 > 知识库问答 >
问题:

将字段添加到已命名的元组中(从以前的字段)

颜畅
2023-03-14

假设我想存储一些关于会议日程的信息,包括演示时间和暂停时间。我可以在NamedTuple中执行此操作。

from typing import NamedTuple

class BlockTime(NamedTuple):
    t_present: float
    t_pause: float

但是,如果我还想存储每个块需要多少,以便t_each=t_pauset_present,我不能只是将其添加为属性:

class BlockTime(NamedTuple):
    t_present: float
    t_pause: float
    # this causes an error
    t_each = t_present + t_pause

在Python中这样做的正确方法是什么?如果我创建了一个< code>__init__(self)方法,并将它作为一个实例变量存储在那里,但是它将是可变的。

共有3个答案

杜辉
2023-03-14

良好的..不能覆盖父级为NamedTuple的类的< code>__new__或< code>__init__。但是您可以重写一个类的< code>__new__,该类继承自另一个其父级为NamedTuple的类。

所以你可以这样做

from typing import NamedTuple

class BlockTimeParent(NamedTuple):
    t_present: float
    t_pause: float
    t_each: float

class BlockTime(BlockTimeParent):
    def __new__(cls, t_present, t_pause):
        return super().__new__(cls, t_present, t_pause, t_present+ t_pause)

b = BlockTime(1,2)
print (b)
# BlockTime(t_present=1, t_pause=2, t_each=3)
金旺
2023-03-14

您可以创建一个构建块时间对象的类方法

class BlockTime(NamedTuple):
    t_present: float
    t_pause: float
    t_each: float
    @classmethod
    def factory(cls, present, pause):
        return cls(present, pause, present+pause)

print(BlockTime.factory(1.0, 2.0))
# BlockTime(t_present=1.0, t_pause=2.0, t_each=3.0)

编辑:

下面是使用新的Python 3.7数据类的解决方案

from dataclasses import dataclass, field

@dataclass(frozen=True)
class BlockTime:
    t_present: float
    t_pause: float
    t_each: float = field(init=False)
    def __post_init__(self):
        object.__setattr__(self, 't_each', self.t_present + self.t_pause)

冻结的数据类es不是完全不可变的,但它们非常接近,这让您可以自然地创建实例BlockTime(1.0,2.0)

关正雅
2023-03-14

如果它不是真正存储的,而是动态计算的,你可以为它使用一个简单的属性

from typing import NamedTuple

class BlockTime(NamedTuple):
    t_present: float
    t_pause: float
    @property
    def t_each(self):
        return self.t_present + self.t_pause

>>> b = BlockTime(10, 20)
>>> b.t_each  # only available as property, not in the representation nor by indexing or iterating
30

这样做的好处是,您永远不会(甚至不会意外)为它存储错误的值。然而,以根本没有实际存储为代价。因此,为了让它看起来像是存储的,您必须至少覆盖__getitem____iter____repr__-这可能会带来太多麻烦。

例如,Patrick Haugh给出的NamedTuple方法有一个缺点,即仍然可能创建不一致的BlockTime或丢失部分namedtuple便利性:

>>> b = BlockTime.factory(1.0, 2.0)
>>> b._replace(t_present=20)
BlockTime(t_present=20, t_pause=2.0, t_each=3.0)

>>> b._make([1, 2])
TypeError: Expected 3 arguments, got 2

事实上,您实际上有一个必须与其他字段同步的“计算”字段,这表明您可能根本不应该存储它以避免不一致的状态。

 类似资料:
  • Proto3已被简化,不再支持“必需”和“可选”字段(请参见为什么在协议缓冲区3中删除“必需”和“可选”)。是否仍有办法将某个字段标记为必填字段?我研究了FieldOptions(字段选项),并尝试了以下方法: 在将其编译成Java代码之后,当我检查编译的Java代码时,我没有看到字段与proto中指定的元数据之间的任何链接。我错过什么了吗?

  • 问题内容: 我有一个字段是,保持日期值,我从转换到。 有些记录有八个字符,有些记录有七个字符。我想通过将前导零添加到具有7的前导零来使它们具有相同的长度。 8个字符的示例:12162003 7个字符的示例:5072004(需要前导零) 查询: 问题答案: 可以在更多情况下使用的功能是REPLICATE。它将一个X值的次数连接到一个字符串。 这将花费您的生日的长度,将其减去8,然后在前面放置多个前导

  • 问题内容: 我正在使用wtforms(和flask)生成动态表单。我想向正在生成的字段中添加一些自定义的CSS类,但是到目前为止,我一直无法这样做。使用在这里找到的答案,我尝试使用自定义小部件来添加此功能。它的实现方式与该问题的答案几乎完全相同: 在View中,我这样做是为了创建字段(ClassedTextField是从表单导入的,而f是基本表单的实例): 表单的其余部分均已正确创建,但此jinj

  • 问题内容: 将字段添加到结构化numpy数组的最干净方法是什么?可以破坏性地完成它,还是必须创建一个新数组并在现有字段上进行复制?每个字段的内容是否连续存储在内存中,以便可以高效地进行复制? 问题答案: 如果您使用的是numpy 1.3,则还有numpy.lib.recfunctions.append_fields()。 对于许多安装,您将需要访问它。不允许一个人看到

  • 我想计算两个字段的总和,然后在文档中创建新的字段,比如:“total sum”。但我不知道怎么做。都在MongoDB中。这里有一个例子:

  • 我使用iText将数据填充到PDF中现有的AcroForm字段中。 我现在正在寻找将新的AcroForm字段添加到PDF的解决方案。iText是否可以做到这一点?如果是,我该如何做到这一点?