Pra*_*rni 3 python python-3.x python-typing
请检查下面的代码
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())
Run Code Online (Sandbox Code Playgroud)
我收到一个错误。在父类中A,我想定义方法f,以便指示任何子类都应该通过返回仅由ot字段NamedTuple组成的a 来覆盖它。intstr
但我收到一条错误消息:
TypeError: 'NamedTupleMeta' object is not subscriptable
Run Code Online (Sandbox Code Playgroud)
如下更改签名会有所帮助,但是我如何告诉打字系统子类可以返回仅包含 int 和 str 的 NamedTuples
TypeError: 'NamedTupleMeta' object is not subscriptable
Run Code Online (Sandbox Code Playgroud)
    问题是从根本上来说typing.NamedTuple这不是一个正确的类型。collections.namedtuple它本质上允许您使用继承和类型注释的语法来使用类工厂。这是糖。
这是误导性的。通常,当我们期望:
class Foo(Bar):
    pass
foo = Foo()
print(isinstance(foo, Bar))
Run Code Online (Sandbox Code Playgroud)
始终打印True. 但typing.NamedTuple实际上,通过元类机制,只是使某些东西成为 的后代tuple,就像 一样collections.namedtuple。实际上,它存在的唯一原因是使用NamedTupleMetaclass来拦截类创建。也许以下内容会有所启发:
>>> 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
Run Code Online (Sandbox Code Playgroud)
有些人可能会觉得这很肮脏,但正如 Python 之禅中所说,实用性胜过纯粹性。
请注意,人们经常会混淆collections.namedtuple哪个本身不是类,而是类工厂。所以:
>>> 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
Run Code Online (Sandbox Code Playgroud)
namedtuple尽管请注意,由/生成的类在您继承它们时确实会按预期行事NamedTuple 。
请注意,您的解决方案:
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())
Run Code Online (Sandbox Code Playgroud)
没有通过 mypy:
(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)
Run Code Online (Sandbox Code Playgroud)
然而,usintTuple确实:
class A(abc.ABC):
    @abc.abstractmethod
    def f(self) -> typing.Tuple[typing.Union[str, int],...]:
        ...
Run Code Online (Sandbox Code Playgroud)
虽然,这可能不是很有用。
您真正想要的是某种结构类型,但我想不出任何方法可以用于typing.Protocol此目的。基本上,它不能表达“具有可变数量属性的任何类型,所有这些属性都是typing.Union[int, str].
|   归档时间:  |  
           
  |  
        
|   查看次数:  |  
           6211 次  |  
        
|   最近记录:  |