简体   繁体   English

在方法签名中自动使用子类类型

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM