【问题标题】:Type hinting a list with coupled inheritance类型提示具有耦合继承的列表
【发布时间】:2020-06-14 18:57:32
【问题描述】:

我正在使用 Python 3.7.6 和 PyCharm。我希望我的代码作为一个很好的内部 API 工作,并为对象显示代码完成,所以我想使用打字。

我正在尝试为何时找到一个好的模式:

  • 有两组类,每组都有自己的继承树
  • 一组中的对象由另一组中的对象列表组成

(以下示例)

我在下面找到了一种方法,但感觉就像是 hack。什么是正确(或更好)的方法?

from typing import List, Type

class Leg:
    def step(self):
        print("step")

class DuckLeg(Leg):
    def paddle(self):
        print("splosh")

class Biped:
    def __init__(self, leg_type: Type[Leg]):
        self.legs: List[leg_type] = [leg_type(), leg_type()]

    def walk(self):
        for leg in self.legs:
            leg.step()

class Duck(Biped):
    def __init__(self):
        super().__init__(leg_type=DuckLeg)
        self.legs: List[DuckLeg] = self.legs  # A hack?

my_duck = Duck()
my_duck.walk()              # code-completion appears for .walk()
my_duck.legs[0].paddle()    # code-completion appears for .paddle()

编辑1:这个问题不是关于在哪里放置类型注释,而是如何确保代码完成在这种情况下工作。如果以下行被注释掉...

self.legs: List[DuckLeg] = self.legs

...由于鸭子打字,代码仍将运行,但 .paddle() 不会出现代码完成,当手动输入 PyCharm 代码检查时将报告:未解析的属性引用 'paddle' 类 'Leg'。

【问题讨论】:

  • @mkrieger1 感谢您的评论。这是一本有趣的书,但不幸的是没有回答我的问题。这与在类定义中放置类型注释的位置无关(参见上面的编辑)。
  • 但是如果你注释掉那一行,然后在class Duck(Biped) 下添加legs: List[DuckLeg] 行呢?这不会有同样的效果,而不是一个黑客?
  • @mkrieger1 感谢您回来。我同意这将不是一个黑客。遗憾的是,如果没有分配,它并没有给我我正在寻找的漂亮的内部 API(出于我不明白的原因)。所以仍然没有代码完成,仍然按照您建议的方式进行代码检查错误。

标签: python inheritance pycharm type-hinting


【解决方案1】:

不确定这是否真的解决了你的问题,但我认为它比你建议的更干净:

from typing import List, Type

class Leg:
    def step(self):
        print("step")

class DuckLeg(Leg):
    def paddle(self):
        print("splosh")

class Biped:
    LegType = Leg
    def __init__(self):
        # self.LegType always gives the correct leg type for the instance
        self.legs: List[self.LegType] = [self.LegType(), self.LegType()]

    def walk(self):
        for leg in self.legs:
            leg.step()

class Duck(Biped):
    LegType = DuckLeg
    def __init__(self):
        super().__init__()

【讨论】:

  • 感谢@jdehesa 的建议。我同意它更具可读性并且可以运行。不幸的是,有两个问题:Biped.__init__ 方法中的 List[self.LegType] 现在引发了 self.LegType 的红色代码检查错误“invalid self”。我尝试将其更改为 Biped.LegType,但这无济于事,因为 Biped.LegType 是 Leg,即使在 init 中也是如此。我猜是一个不变的类变量。回到最初的问题,.paddle() 的代码检查没有出现,当手动输入时,代码检查将其标记为警告。不过谢谢。我学到了一些东西:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-08-24
  • 2019-08-15
  • 1970-01-01
相关资源
最近更新 更多