【问题标题】:python subclass list and matching genericpython子类列表和匹配的泛型
【发布时间】:2022-10-14 12:22:01
【问题描述】:

我发现它能够以这种方式或通过 throw __new__ 进行子类化,没有问题,但是类型检查。

class a(tuple):
    pass

print(a((1, 2, 3)))  # <---- ( 1, 2, 3 )

b: tuple[int, int, int] = a((1, 2, 3))  # <--- Error
# Incompatible types in assignment (expression has type "a", variable has type "Tuple[int, int, int]")

c: tuple = a((1, 2, 3))  # <--- Ok  

d: tuple[int, int, int] = (1, 2, 3)  # <--- Ok  

子类列表的工作方式相同。

    class a( list[ T ] ) 
 
        def __init__(self, * pax : T  )  : pass

    b : list[ int ] = a( 1, 2 ) # <--- Ok  

    c = a[ int ]( 1, 2 ) # <--- Ok  

如何正确子类化元组?谢谢你的建议。

【问题讨论】:

  • @j1-lee 一样。顺便说一句,我建议@Micah 使用Tuple[int, ...]Tuple[int, int, int] 而不是tuple[int, int, int] by from typing import Tuple
  • Python 3.10.5,使用 Tuple 得到相同的 mypy 错误
  • 诡异的。我在 3.10.6 中没有错误。见codepaste.xyz/posts/yNMuXCiujJqobjQgMZcL
  • @hide1nbush b: Tuple[int, ...] = a((1, 2, 3))b: tuple[int, int, int] = a((1, 2, 3)) 不一样
  • 关于在子类上保留类型参数的能力(如a[int,int,str]),即可变参数泛型,请参阅discussion in comments to this question。建议的答案在这里不起作用(因为您需要一个子类而不是别名),但 PEP646 讨论了您的(唯一?)方法,仍然缺乏mypy 支持。

标签: python generics subclass mypy typing


【解决方案1】:

您感到困惑的问题与子类化无关,但由于 mypy 的假设而具有一切任何序列作为参数传递给任何tuple 及其子类的名称(例如tuple((item, item, ..., item)),与Python 元组语法(item, item, ..., item,) 不同)具有签名Tuple[Any, ...](因为这是默认的类型签名tuple 构造函数)。考虑以下代码示例:

one_tuple: tuple[int] = tuple((1,))
answer: tuple[int] = (1,)
print(one_tuple == answer)

使用python 运行上述代码将产生输出True,这是预期的结果。但是,mypy 将产生以下错误消息:

onetuple.py:1: error: Incompatible types in assignment (expression has type "Tuple[int, ...]", variable has type "Tuple[int]")
Found 1 error in 1 file (checked 1 source file)

鉴于不可能使用 Python 的标准元组语法来生成其子类的实例(因为它总是产生一个tuple),那么tuple 的任何子类(例如class MyTuple(tuple): ...) 将因此不能满足任何Tuple[T],其中T 不是可变长度的序列。

虽然问题中没有说明以下断言,但如果您确定您的 tuple 子类将有一些有限的长度,这可能是一个合适的解决方法:

class MyTuple(tuple[int, int, int]):
    pass

mytuple: tuple[int, int, int] = MyTuple((1, 2, 3))

在这种情况下,mypy 不会产生任何验证错误。

作为附录,随着PEP 646 - Variadic Generics 的引入,这可能从 Python 3.11 开始成为可能,但是 mypy 尚不支持此功能(请参阅 GitHub 问题 python/mypy#12840,在新类型功能下,PEP 646 - 截至 2022 年 10 月 14 日,尚未在此处跟踪任何子问题),并且 pyrightpyre 似乎没有正确检查声明 one_tuple: tuple[int] = tuple((1, 2,)) 无效,因此我在这里结束我的进一步努力现在鉴于我不确定它是否确实正确支持 PEP 646。

【讨论】:

  • 是的,如果我想像元组本身一样动态分配不同数量的泛型,这种方式确实有效。我应该怎么办?
  • @Micah您基本上必须使用预期的签名(即参数数量)为您的tuple 子类覆盖__new__ 方法,但随后您将遇到尚未修复的issue
  • 在他的情况下,使用 tuple.__new__( cls , iterable ) 可以解决问题。但我认为我的问题与如何分配动态数量的泛型有关。
  • 这个例子可以给我们分配相同类型的选项,但是元组可以有不同的类型,我们该怎么做呢? stackoverflow.com/questions/67529338/…
  • 我将只使用默认的tuple[...] 签名并为某些定义的tuple[...] 的具体一次性别名保留子类。老实说,目前无法在 Python/mypy 中验证/表达您所要求的内容。尝试在mypy issue tracker 上报告您想要的问题。
猜你喜欢
  • 1970-01-01
  • 2023-03-06
  • 2015-04-20
  • 1970-01-01
  • 2011-09-09
  • 2013-12-21
  • 1970-01-01
  • 1970-01-01
  • 2020-09-02
相关资源
最近更新 更多