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

一种用于类型检查的子类命名单元的方法

陆臻
2023-03-14

我有几个命名的,共享一些字段。我有一个接受这些元组的函数,并保证只与共享字段交互。我想在mypy中键入检查此类代码。

代码的一个示例是:

from typing import NamedTuple

class Base(NamedTuple):
    x: int
    y: int


class BaseExtended(NamedTuple):
    x: int
    y: int
    z: str

def DoSomething(tuple: Base):
    return tuple.x + tuple.y

base = Base(3, 4)
base_extended = BaseExtended(5, 6, 'foo')

DoSomething(base)
DoSomething(base_extended)

当我对这段代码运行mypy时,我得到了一个可预见的错误:

mypy_example.py:20:错误:“DoSomething”的参数1具有不兼容的类型“base extended”;预期的“基数”

有没有办法构造我的代码并保持我的py类型检查?我无法从< code>Base继承< code>BaseExtended,因为在< code>NamedTuple继承实现中有一个错误。

我也不想使用丑陋的联合[基数,基数扩展],因为当我尝试键入检查列表时,这会中断,因为列表[联合[基,基扩展]]不等于列表[基扩展],因为关于变体/协变类型的一些神秘的魔力。

我应该放弃这个想法吗?

共有2个答案

邵华皓
2023-03-14

PEP 544建议对类型系统进行扩展,以允许结构子类型化(静态duck类型化)。此外,类型的运行时实现。NamedTuple将很快得到改进,可能在6月底的Python 3.6.2中(这也将通过在PyPI上键入

廉高邈
2023-03-14

构造命名元组的方式继承了< code >类型。NamedTuple类尚不可能。您必须编写自己的元类来扩展< code >类型。NamedTupleMeta类来实现子类化,即使这样,由< code > collections . named tuple()生成的类也不是为扩展而构建的。

相反,您希望使用新的dataclasses模块来定义类并实现继承:

from dataclasses import dataclass

@dataclass(frozen=True)
class Base:
    x: int
    y: int

@dataclass(frozen=True)
class BaseExtended(Base):
    z: str

该模块在Python 3.7中是新的,但您可以pip安装数据类Python 3.6上的反向端口。

上面用< code>x和< code>y属性定义了两个不可变的类,其中< code>BaseExtended类增加了一个属性。< code>BaseExtended是< code>Base的完整子类,因此出于键入目的,它符合< code>DoSomething()函数的要求。

这些类不是完整命名的元组,因为它们没有长度或不支持索引,但这是通过创建继承自collections.abc.Sequence的基本类来添加的,添加了两个方法来按索引访问字段。如果您将order=True添加到@dataclass()装饰器,那么您的实例就可以像(命名的)元组一样完全排序:

from collections.abc import Sequence
from dataclasses import dataclass, fields

class DataclassSequence(Sequence):
    # make a dataclass tuple-like by accessing fields by index
    def __getitem__(self, i):
        return getattr(self, fields(self)[i].name)
    def __len__(self):
        return len(fields(self))

@dataclass(frozen=True, order=True)
class Base(DataclassSequence):
    x: int
    y: int

MyPy将很快明确支持< code > data classes ;在0.600版本中,您仍然会得到错误,因为它不能识别< code>dataclasses模块导入或生成了< code>__new__方法。

在Python 3.6及更早版本中,您还可以安装attrs项目来实现相同的效果;使用attrs,上面的序列基类如下所示:

from collections.abc import Sequence
import attr

class AttrsSequence(Sequence):
    # make a dataclass tuple-like by accessing fields by index
    def __getitem__(self, i):
        return getattr(self, attr.fields(type(self))[i].name)
    def __len__(self):
        return len(attr.fields(type(self)))

@attr.s(frozen=True, auto_attribs=True)
class Base(AttrsSequence):
    x: int
    y: int

< code>dataclasses直接基于< code>attrs,其中< code>attrs提供了更多功能;mypy完全支持用< code>attrs生成的类。

 类似资料:
  • 问题内容: 我有几个共享一些字段的namedtuple。我有一个接受这些元组的函数,并保证仅与共享字段进行交互。我想在mypy中对此类代码进行类型检查。 该代码的示例为: 当我在此代码上运行mypy时,我得到一个可预测的错误: mypy_example.py:20:错误:“ DoSomething”的参数1具有不兼容的类型“ BaseExtended”;预期的“基础” 有没有办法构造我的代码并保持

  • 问题内容: 如果我有字典,并且想检查一下,则可以将其作为一个块(非常好!),也可以使用方法作为默认值。 我想为做同样的事情。也就是说,如果尚未设置对象,我已经有要返回的对象,但这给了我类似的错误 AttributeError:’bool’对象没有属性’attribute’ 问题答案: 更直接的类似物比是。 (在哪里是可选的,如果未找到,则在no属性上引发异常。) 例如,您将通过。

  • 如果按照“字节”->“短”->“int”->“长”->“浮点”->“双倍”的自动转换,那么输出应该打印“双倍”,对吗? (https://www.geeksforgeeks.org/type-conversion-java-examples/)

  • 我如何确认通过props(例如)接收的反应元素在我的渲染方法中属于给定类型? 假设我有一个元素和一个元素。在的render方法中,我想查找传递的所有子项,并对s中的任何子项执行一些特殊的操作。 我确实找到了一个可行的实现,但只是在反复试验之后。请参阅下面的代码。(第15.4.2节) 我ist.jsx 名单我tem.jsx 所以,最后一个实现似乎可以工作,但是为什么第一个实现不能工作呢?我在reac

  • 我试图使使用该类注册的任何元块中的子块只需要一个类来命名,也就是说,将它们命名为参数值,但不使用参数值。 虽然这是围绕一个API(Minecraft Forge)展开的,但我认为这是一个Java问题,所以我在这里快速解释一下我打算做什么。 元块由子块组成,子块是同一块的变体(例如,同一块,但仅纹理和名称发生变化)。每个子块都需要一个名称来标识它。这些名称以的形式列在类中,然后以(例如:,,等等),