PEP-484 隐形继承属性的类型提示

问题描述 投票:0回答:1

如何输入来自未声明基类的

@property
(使用 mixin 时经常发生)?

例如为了注释来自隐藏继承层次结构的“预期属性”,我使用:


class SomeMixin:

  name: str
  logger: Logger

  def __init__(self):
    super().__init__()

我们总是在继承层次结构中使用

SomeMixin
来证明
self.name
self.logger
类型的属性
str
Logger
。到目前为止,一切都很好。

如果要使用 mixin,其中

logger
由另一个类提供,实际上是一个属性,例如:

@property
def logger(self):
  return self.__logger

如何在 mixin 中输入提示?我可以继续使用上面的现有属性类型提示,但随后在类型检查时收到“不兼容的覆盖”错误,因为

logger
实际上不是属性,例如:


class Base:

  @property
  def logger(self) -> Logger:
    return Logger("foo")

class Derived(SomeMixin, Base):
  pass

类型检查器会抱怨

Dervied
logger
的定义不兼容,例如,在 Pyright 中:

Base classes for class "Derived" define variable "logger" in incompatible wayPylancereportIncompatibleVariableOverride
foo.py(17, 9): Base class "Base" provides type "property", which is overridden
foo.py(9, 5): Base class "SomeMixin" overrides with type "Logger"

我可以使用类似的东西:


class SomeMixin:

  name: str
  logger: property

...但是

logger
具有类型
Any
并且我没有得到对其值进行类型检查的好处。

python python-3.x python-typing
1个回答
0
投票

这是 python 的一个怪癖,

@property
和常规属性本质上被视为不同的类型。要解决您的问题,您需要在
SomeMixin
中指定 logger 是一个属性:

class Logger:
    def __init__(self, s:str) -> None:
      pass

class SomeMixin:
    name: str

    @property
    def logger(self) -> Logger:
        raise NotImplementedError

    def __init__(self):
        super().__init__()

class Base:
    @property
    def logger(self) -> Logger:
        return Logger("foo")

class Derived(Base, SomeMixin):
    pass

我还建议使用抽象基类来确保该属性被使用

SomeMixin
的类覆盖。这只是确保您无法在不将其与另一个类组合以覆盖该方法的情况下初始化
SomeMixin

from abc import ABC, abstractmethod

class Logger:
    def __init__(self, s:str) -> None:
      pass

class SomeMixin(ABC):
    name: str

    @property
    @abstractmethod
    def logger(self) -> Logger:
        ...

    def __init__(self):
        super().__init__()

class Base:
    @property
    def logger(self) -> Logger:
        return Logger("foo")

class Derived(Base, SomeMixin):
    pass

关于继承的旁注:请注意,我在

Base
中切换了
SomeMixin
Derived
- 这样
Base
就会覆盖
SomeMixin
,而不是相反。

© www.soinside.com 2019 - 2024. All rights reserved.