[英]Automatically use subclass type in method signature
I have a parent class with many subclasses in Python 3. Currently, the hierarchy looks something like this:我有一个父类 class,在 Python 3 中有许多子类。目前,层次结构如下所示:
class Parent:
@classmethod
def check(cls, obj: "Parent"):
pass
class Child1(Parent):
def __init__(self, x):
self.x = x
@classmethod
def check(cls, obj: Parent) -> "Child1":
if cls == obj.__class__:
return obj
else:
raise TypeError("Bad type received.")
class Child2(Parent):
def __init__(self, y):
self.y = y
@classmethod
def check(cls, obj: Parent) -> "Child2":
if cls == obj.__class__:
return obj
else:
raise TypeError("Bad type received.")
... many more children here ...
And then there is another hierarchy that uses these classes:然后还有另一个使用这些类的层次结构:
from abc import abstractmethod, ABC
class Runnable(ABC):
@abstractmethod
def run(self) -> Parent:
pass
class Thing1(Runnable):
def run(self) -> Parent:
... do a thing that produces a Child1 ...
class Thing2(Runnable):
def run(self) -> Parent:
... do a thing that produces a Child2 ...
There are places where I call Thing1.run()
and need to access its field x
.有些地方我调用
Thing1.run()
并需要访问它的字段x
。 Python allows this, but it is not type-safe. Python 允许这样做,但它不是类型安全的。 The purpose of
check()
is to be a kind of assert and cast, so that using Child1.check(Thing.run()).x
is type-safe but can raise an error. check()
的目的是成为一种断言和强制转换,因此使用Child1.check(Thing.run()).x
是类型安全的,但会引发错误。
But as you can see, Child1.check()
and Child2.check()
have an identical implementation;但是正如您所见,
Child1.check()
和Child2.check()
具有相同的实现; the only thing that changes is their return type.唯一改变的是它们的返回类型。 I have many such child classes, so I have repeated implementations for no good reason.
我有很多这样的子类,所以我无缘无故地重复实现。 Is there a way to write the following in actual Python, so that duplicating the implementations is no longer needed?
有没有办法在实际 Python 中编写以下内容,以便不再需要重复实现?
class Parent:
@classmethod
def check(cls, obj: Parent) -> cls: # <--- This return type is not allowed in real Python
if cls == obj.__class__:
return obj
else:
raise TypeError("Bad type received.")
For python 3.10 and before, you can do something like:对于 python 3.10 及之前的版本,您可以执行以下操作:
from typing import Type, TypeVar
ParentType = TypeVar("ParentType", bound="Parent")
class Parent:
@classmethod
def check(cls: Type[ParentType], obj: Parent) -> ParentType:
...
Starting with Python 3.11, they are introducing theSelf
type which can be used directly:从Python 3.11开始,他们引入了可以直接使用的
Self
类型:
from typing import Self
class Parent:
@classmethod
def check(cls, obj: Parent) -> Self:
...
SeePEP-673 for more information on Self
.有关
Self
的更多信息,请参阅PEP-673 。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.