简体   繁体   English

Python 3 基类类型注解只允许当前子类

[英]Python 3 base class type annotation only allow the current subclass

Let's say I've got three classes, one parent class, and two subclasses:假设我有三个类,一个父类和两个子类:

class BaseModel:
    def merge(self, other):
        return self + other

class ChildA(BaseModel):
    pass

class ChildB(BaseModel):
    pass

The parent class has a method that takes another instance of the current class and returns a new instance of the current class (out of scope for this question).父类有一个方法,它接受当前类的另一个实例并返回当前类的一个新实例(超出了这个问题的范围)。

How do I annotate BaseModel.merge to restrict it to only the current subclass?如何注释BaseModel.merge以将其限制为仅当前子类?

I can do something like this:我可以做这样的事情:

def merge(self, other: BaseModel) -> BaseModel:
    return self + other

But this still allows me to pass an instance of ChildB into ChildA , since both inherit from BaseModel .但这仍然允许我将ChildA的实例ChildBChildA ,因为两者都继承自BaseModel I only want ChildA to be allowed in ChildA , and ChildB to be allowed for ChildB .我只想ChildA在被允许ChildA ,并ChildB被允许ChildB How can I do that without reimplementing merge on each subclass?如何在不重新实现每个子类的merge情况下做到这一点?

Annotate both arguments with a type variable, to enforce that both arguments must be of the same type.用类型变量注释两个参数,以强制两个参数必须是相同的类型。

from typing import TypeVar

B = TypeVar('B', bound='BaseModel')

class BaseModel:
    def __init__(self, x: int):
        self.x = x

    def __add__(self: B, other: B) -> B:
        return type(self)(self.x + other.x)

    def merge(self: B, other: B) -> B:
        return self + other

class ChildA(BaseModel):
    pass

class ChildB(BaseModel):
    pass


print(ChildA(3).merge(ChildA(4)).x)  # Valid; both arguments are ChildA      
print(ChildA(3).merge(ChildB(4)).x)  # Invalid; one ChildA and one ChildB

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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