我有以下类层次结构:
#!/usr/bin/env python3
from typing import List, Optional, Tuple, Type
class Attribute:
def __init__(self, name: bytes) -> None:
self._name = name
@property
def name(self) -> bytes:
return self._name
class Element:
def __init__(self, name: bytes, attributes: Tuple[Type['Attribute'], ...], elements: Tuple['Element', ...]) -> None:
self._name = name
self._elements = elements
self._attributes = attributes
@property
def name(self) -> bytes:
return self._name
@property
def elements(self) -> Tuple['Element', ...]:
return self._elements
@property
def attributes(self) -> Tuple[Type['Attribute'], ...]:
return self._attributes
class SubAttribute1(Attribute):
def __init__(self, name: bytes, field1: bytes) -> None:
super().__init__(name)
self._afield1 = field1
class SubElement1(Element):
def __init__(self, name: bytes, attributes: Tuple[Type[Attribute], ...], elements: Tuple['Element', ...], field1: bytes, field2: bytes) -> None:
super().__init__(name, attributes, elements)
self._field1 = field1
self._field2 = field2
if __name__ == '__main__':
subE = SubElement1(b'name', None, None, b'', b'')
subA = SubAttribute1(b'name', b'field1')
subE2 = SubElement1(b'name', (subA,), (subE,), b'', b'')
print(subE2.elements[0]._field1)
print(subE2.attributes[0]._afield1)
print(type(subE2.elements[0]))
我子类化基类Element和Attribute来添加额外的字段。字段'elements'和'attributes'应该分别存储派生类对象。对于SubElement1 SubElement1().elements存储一个带有SubElement1对象的元组。所有工作正常,但我得到以下mypy错误:
question.py:45: error: Argument 2 to "SubElement1" has incompatible type "Tuple[SubAttribute1]"; expected "Tuple[Type[Attribute], ...]"
question.py:46: error: "Element" has no attribute "_field1"
question.py:47: error: "Type[Attribute]" has no attribute "_afield1"
我如何更改代码以消除mypy错误?
1条答案
按热度按时间2ledvvac1#
这个问题挺有意思的,我以为PEP 646的支持稍微好一点。
除非明确指定,否则我假定python 3.10和特定检查器的最新发布版本:第一个月
pyright==1.1.281
使
elements
正确首先,以下代码(足够简单)解决了“元素”问题,但对属性没有帮助:
这会产生一个错误(在源代码中注解). Here's playground。
在不久的将来(甚至可以在
mypy
master
分支上使用,但不能在0.991
分支上使用),您将能够用from typing_extensions import Self
替换_Self
,并跳过对self
参数的注解,如下所示:你可以试试here-同样的1错误。
变量
attributes
现在你想保留
attributes
类型--它们可以是异构的,因此你需要PEP 646来继续。该类在未知数量的变量中成为泛型。pyre
和pyright
声明支持这一点(mypy
没有,工作当前正在进行中)。pyre
未能对以下解决方案进行类型检查,pyright
成功了(虽然我个人不喜欢它,所以不建议切换)。Pyright沙箱是非官方的,不是最新的,在这里不起作用-复制到本地,安装并运行pyright
来验证。Pyright
表示0 errors, 0 warnings, 0 informations
,pyre
错误:mypy
完全疯狂,甚至与实验旗帜,粘贴到mypy
操场,如果你想看看这个。均匀
attributes
然而,如果属性可以用同构序列表示(比如说,
SubElement1
示例可以只包含SubAttribute1
),事情就简单多了,带有常规TypeVar
的泛型就足够了:还有这个。
奖金
你展示的所有代码都叫做“用Python编写Java”(Citation)。你肯定不需要简单属性访问的getter,因为你可以在以后添加它们。你不应该手工编写数据类--
dataclasses
标准模块会做得更好。所以,你的示例实际上简化为更简洁和可维护的python:...并且可以正常工作。很快就可以正常工作-目前
mypy
不完全支持Self
,检查此问题会导致内部错误(崩溃),reported here by me。Pyright
响应时没有错误。