英文:
Type hint issue when base class is parameterized on a value type and has methods that return that type
问题
这是一个用于说明问题的玩具示例:
from typing import Type
from dataclasses import dataclass, asdict
import json
@dataclass
class ValueType1:
x: int
y: int
@dataclass
class ValueType2:
x: int
z: str
class FooBase:
def __init__(self, value_cls: Type[ValueType1|ValueType2], name: str):
self.name = name
self.value_cls = value_cls
def save(self, value: ValueType1|ValueType2):
with open(self.name+'.json', 'w') as f:
json.dump(asdict(value), f)
def load(self) -> ValueType1|ValueType2:
with open(self.name+'.json', 'r') as f:
return self.value_cls(**json.load(f))
class Foo1(FooBase):
def __init__(self):
super().__init__(value_cls=ValueType1, name='1')
class Foo2(FooBase):
def __init__(self):
super().__init__(value_cls=ValueType2, name='2')
foo1 = Foo1()
foo2 = Foo2()
foo1.save(ValueType1(x=10, y=20))
foo2.save(ValueType2(x=10, z='a'))
res1 = foo1.load()
res2 = foo2.load()
print(res1.y)
print(res2.z)
这个示例可以正常工作,如预期地打印出20和'a',但是在res1.y
和res2.z
处会显示类型错误(仅显示res1.y
错误)。
Type of "y" is unknownPylancereportUnknownMemberType
Type of "y" is partially unknown
Type of "y" is "int | Unknown"PylancereportUnknownMemberType
Argument type is partially unknown
Argument corresponds to parameter "values" in function "print"
Argument type is "int | Unknown"PylancereportUnknownArgumentType
Cannot access member "y" for type "ValueType2"
Member "y" is unknownPylancereportGeneralTypeIssues
(variable) y: int | Unknown
我想知道是否有一些类型提示的技巧可以解决这个问题,让res1
的类型清晰地显示为ValueType1
。谢谢!
英文:
This a toy example to illustrate the issue:
from typing import Type
from dataclasses import dataclass, asdict
import json
@dataclass
class ValueType1:
x: int
y: int
@dataclass
class ValueType2:
x: int
z: str
class FooBase:
def __init__(self, value_cls: Type[ValueType1|ValueType2], name: str):
self.name = name
self.value_cls = value_cls
def save(self, value: ValueType1|ValueType2):
with open(self.name+'.json', 'w') as f:
json.dump(asdict(value), f)
def load(self) -> ValueType1|ValueType2:
with open(self.name+'.json', 'r') as f:
return self.value_cls(**json.load(f))
class Foo1(FooBase):
def __init__(self):
super().__init__(value_cls=ValueType1, name='1')
class Foo2(FooBase):
def __init__(self):
super().__init__(value_cls=ValueType2, name='2')
foo1 = Foo1()
foo2 = Foo2()
foo1.save(ValueType1(x=10, y=20))
foo2.save(ValueType2(x=10, z='a'))
res1 = foo1.load()
res2 = foo2.load()
print(res1.y)
print(res2.z)
This works fine and prints 20 and 'a' as expected but typing errors are shown at res1.y
and res2.z
of this sort (only res1.y
errors shown):
Type of "y" is unknownPylancereportUnknownMemberType
Type of "y" is partially unknown
Type of "y" is "int | Unknown"PylancereportUnknownMemberType
Argument type is partially unknown
Argument corresponds to parameter "values" in function "print"
Argument type is "int | Unknown"PylancereportUnknownArgumentType
Cannot access member "y" for type "ValueType2"
Member "y" is unknownPylancereportGeneralTypeIssues
(variable) y: int | Unknown
I'm wondering if there is some type hinting magic that can resolve this and make it clear that res1
is of type ValueType1
. Thanks!
答案1
得分: 1
你可以这样做:
from typing import Callable
class Foo1(FooBase):
load: Callable[[], ValueType1]
def __init__(self):
super().__init__(value_cls=ValueType1, name='1')
class Foo2(FooBase):
load: Callable[[], ValueType2]
def __init__(self):
super().__init__(value_cls=ValueType2, name='2')
有些编辑器可能会将 load()
识别为属性而不是函数,并且颜色显示可能不正确,但类型提示将正常工作。
英文:
you could do this:
from typing import Callable
class Foo1(FooBase):
load: Callable[[], ValueType1]
def __init__(self):
super().__init__(value_cls=ValueType1, name='1')
class Foo2(FooBase):
load: Callable[[], ValueType2]
def __init__(self):
super().__init__(value_cls=ValueType2, name='2')
Some editors will now pick load()
up as a attribute and not a function and color it wrong though. But type hints will work properly
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论