代码之家  ›  专栏  ›  技术社区  ›  Nils

Typehint一种使用超类类方法返回新实例的方法

  •  -1
  • Nils  · 技术社区  · 7 月前
    from typing import Self, Union
    
    
    class Superclass:
        @classmethod
        def from_dict(cls, dict_: dict[str, str]) -> Self:
            return cls(**dict_)
    
    
    class Subclass(Superclass):
        def __init__(self, name: Union[str, None] = None):
            self.name = name
    
        def copy(self) -> Self:
            return Subclass.from_dict({'name': self.name})
    

    我在底线上发现了一个错误,

    类型“子类”不能分配给返回类型Self@Subclass"

    我也试过了

    from typing import Type, TypeVar, Union, Dict
    
    T = TypeVar('T', bound='Superclass')
    
    class Superclass:
        @classmethod
        def from_dict(cls: Type[T], dict_: dict[str, str]) -> T:
            return cls(**dict_)
    
    
    class Subclass(Superclass):
        def __init__(self, name: Union[str, None] = None):
            self.name = name
    
        def copy(self: T) -> T:
            return self.from_dict({'name': self.name})
    

    但这个给了我一个错误

    无法访问类“Superclass*”的属性“name”属性未知


    如何在子类方法内使用超类的类方法生成子类的实例?

    1 回复  |  直到 7 月前
        1
  •  4
  •   user2357112    7 月前

    你这里有三个问题。

    第一个问题是,不能保证 self 具体来说 Subclass .如果你打电话来 copy 关于一个子类的实例 子类 那么 Self 引用该子类,并返回 子类 错了。

    您需要返回任何类型的实例 自己 是的一个实例。最简单的方法就是打电话 from_dict 自己 type(self) 而不是 子类 :

    return self.from_dict({'name': self.name})
    

    …这正是你所做的 在代码的第二个版本中。你解决了这个问题!但你出于某种原因引入了第二个问题。

    在代码的第二个版本中,您切换到使用类型变量 T 而不是 自我 .你的 T 其上限为 Superclass 而不是 子类 :

    T = TypeVar('T', bound='Superclass')
    

    当你在使用它时,这是可以的 超级级 ,但在 子类 ,它会导致新的错误。你需要第二个类型变量 子类 如果你想采用这种方法,这是有限制的,但使用起来会更容易 自我 .

    第三个问题是 self.name 可以是 None .你不能用 没有 作为a的值 dict[str, str] 你必须对此采取行动。