首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Python类型对NamedTuple的支持

Python类型对NamedTuple的支持
EN

Stack Overflow用户
提问于 2020-02-27 09:36:15
回答 1查看 3.6K关注 0票数 1

请检查下面的代码

代码语言:javascript
复制
import typing
import abc


class A(abc.ABC):
    @abc.abstractmethod
    def f(self) -> typing.NamedTuple[typing.Union[int, str], ...]:
        ...


class NT(typing.NamedTuple):
    a: int
    b: str


class B(A):

    def f(self) -> NT:
        return NT(1, "s")


print(B().f())

我犯了个错误。在父类A中,我希望定义方法f,以便指示任何子类都应该通过返回仅由int ot str字段组成的NamedTuple来重写它。

但我有个错误说:

代码语言:javascript
复制
TypeError: 'NamedTupleMeta' object is not subscriptable

按下面的方式更改签名会有所帮助,但我如何告诉输入系统,子类可以返回只有int和str's的NamedTuples

代码语言:javascript
复制
class A(abc.ABC):
    @abc.abstractmethod
    def f(self) -> typing.NamedTuple:
        ...
EN

回答 1

Stack Overflow用户

发布于 2020-02-27 10:04:15

问题是,从根本上说,typing.NamedTuple不是一个合适的类型。它基本上允许您使用类工厂collections.namedtuple,使用继承的语法和类型注释。是糖。

这是误导。通常,当我们期望:

代码语言:javascript
复制
class Foo(Bar):
    pass

foo = Foo()
print(isinstance(foo, Bar))

总是打印True。但实际上,通过元类机器,typing.NamedTuple只是使某些东西成为tuple的后代,就像collections.namedtuple一样。实际上,它存在的唯一原因是使用NamedTupleMetaclass来拦截类创建。也许以下几点是有启发性的:

代码语言:javascript
复制
>>> from typing import NamedTuple
>>> class Employee(NamedTuple):
...     """Represents an employee."""
...     name: str
...     id: int = 3
...
>>> isinstance(Employee(1,2), NamedTuple)
False
>>>
>>> isinstance(Employee(1,2), tuple)
True

有些人可能觉得这很脏,但正如Python的禅宗所述,实用性胜过纯粹。

注意,人们常常对collections.namedtuple感到困惑,它本身不是一个类,而是一个类工厂。所以:

代码语言:javascript
复制
>>> import collections
>>> Point = collections.namedtuple("Point", "x y")
>>> p = Point(0, 0)
>>> isinstance(p, collections.namedtuple)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: isinstance() arg 2 must be a type or tuple of types

尽管注意,namedtuple/NamedTuple生成的类在继承它们时确实起到了预期的作用。

注意,您的解决方案:

代码语言:javascript
复制
import typing
import abc


class A(abc.ABC):
    @abc.abstractmethod
    def f(self) -> typing.Tuple:
        ...


class NT(typing.NamedTuple):
    a: int
    b: str


class B(A):

    def f(self) -> NT:
        return NT(1, "s")


print(B().f())

不通过的类型:

代码语言:javascript
复制
(py38) juan$ mypy test_typing.py
test_typing.py:18: error: Return type "NT" of "f" incompatible with return type "NamedTuple" in supertype "A"
Found 1 error in 1 file (checked 1 source file)

但是,usint Tuple确实:

代码语言:javascript
复制
class A(abc.ABC):
    @abc.abstractmethod
    def f(self) -> typing.Tuple[typing.Union[str, int],...]:
        ...

不过,这可能不是很有用。

您真正想要的是某种结构类型,但我想不出有什么方法可以使用typing.Protocol。基本上,它不能表示“所有属性都是typing.Union[int, str]的任何类型”。

票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/60430110

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档