![](/img/trans.png)
[英]How to type hint a return an instance of a subclass from a list of superclass in Python
[英]Python: how to override type hint on an instance attribute in a subclass?
在深入研究之前,我的问题是:如何在子类中使用类型提示来指定实例属性的不同类型?
如果您不清楚这意味着什么,请阅读以下内容,我在其中制定了一个示例来澄清事情。
完整说明
我有一个抽象的 class Foo
和一个名为SubclassOfFoo
的Foo
子类。
Foo
有一个抽象方法get_something
,它返回 Some 类型的Something
。
Something
有一个名为SubclassOfSomething
的子类。 SubclassOfSomething
有一个附加方法something_special
。
SubclassOfFoo
覆盖get_something
以返回SubclassOfSomething
类型的 object 。 然后, SubclassOfFoo
尝试使用SubclassOfSomething
的方法something_special
。
但是,目前我的 PyCharm 的检查报告Unresolved attribute reference 'something_special' for class 'Something'
。 我正在尝试找出解决此问题的正确方法。
这一切都非常令人困惑,所以我制作了一个很好的小代码片段来帮助这里:
from abc import ABC, abstractmethod
class Something:
def __init__(self):
self.attr = 0
class SubclassOfSomething(Something):
def __init__(self):
Something.__init__(self)
def something_special(self):
self.attr = 1
class Foo(ABC):
def __init__(self):
self.my_class = self.get_something()
@abstractmethod
def get_something(self) -> Something:
pass
class SubclassOfFoo(Foo):
def __init__(self):
Foo.__init__(self)
def get_something(self) -> SubclassOfSomething:
return SubclassOfSomething()
def do_something_special(self):
self.my_class.something_special()
基本上,为了让一切顺利进行,我可以做以下几件事之一:
Foo
中get_something
返回的类型提示SubclassOfFoo
中为self.my_class
使用类型提示来清除问题选项 #1 是我试图避免的
选项#2不错,但我想不通
选项#3 也是一个选项。
我也对其他选择持开放态度,因为我确信有更好的方法。
你能帮我找出处理这个问题的正确方法吗?
我试过的
为了模拟选项#2,我尝试按照这里的建议使用typing.Type
: 类型提示中的子类
但是,这对我不起作用。
您也可以在Something
上提供something_special
方法,并引发NotImplementedError
class Something:
def __init__(self):
self.attr = 0
def something_special(self):
raise NotImplementedError()
这解决了您的类型提示问题,尽管在功能上它会在同一点引发异常(如果您设法以某种方式获得了Something
并尝试调用something_special
,则将是NotImplementedError
而不是AttributeError
)。
也许在某些情况下,您可能只想pass
,这取决于something_special
实际上是什么。
class Something:
def __init__(self):
self.attr = 0
def validate(self):
# doesn't want to perform validation
pass
class SubclassOfSomething(Something):
def __init__(self):
Something.__init__(self)
def validate(self):
if self.attr < 0:
raise ValueError()
重要的基础是确保您的 class 层次结构符合公共接口 - 子类上的公共方法而不是父类上的公共方法违背了这一点,并减少了 class 层次结构中对象的多态性。
您可以在 class 定义的开头给出my_class
属性的类型提示:
class SubclassOfFoo(Foo):
my_class: SubclassOfSomething # <- here
def get_something(self) -> SubclassOfSomething:
return SubclassOfSomething()
def do_something_special(self):
self.my_class.something_special()
之后没有警告Unresolved attribute reference 'something_special' for class 'Something'
from PyCharm 检查,因为现在my_class
已知为SubclassOfSomething
not Something
。
使用 generics:
from abc import ABC, abstractmethod
from typing import Generic, TypeVar
SomethingT = TypeVar('SomethingT', bound='Something')
...
class Foo(ABC, Generic[SomethingT]):
my_class: SomethingT
def __init__(self):
self.my_class = self.get_something()
@abstractmethod
def get_something(self) -> SomethingT:
pass
class SubclassOfFoo(Foo[SubclassOfSomething]):
def __init__(self):
super().__init__()
def get_something(self) -> SubclassOfSomething:
return SubclassOfSomething()
def do_something_special(self):
# inferred type of `self.my_class` will be `SubclassOfSomething`
self.my_class.something_special()
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.