简体   繁体   English

类型提示具有耦合继承的列表

[英]Type hinting a list with coupled inheritance

I'm using Python 3.7.6 with PyCharm.我在 PyCharm 中使用 Python 3.7.6。 I want my code to work as a nice internal API with code completion appearing for objects so I want to use typing.我希望我的代码作为一个很好的内部 API 工作,并为对象显示代码完成,所以我想使用输入。

I'm trying to find a good pattern for when:我正在尝试为以下情况找到一个好的模式:

  • There are two groups of classes with each group having it's own inheritance tree有两组类,每组都有自己的继承树
  • and objects from one group are composed of lists of objects from other group并且来自一组的对象由来自另一组的对象列表组成

(example below) (下例)

I've found a way below but it feels like a hack.我在下面找到了一种方法,但感觉就像一个黑客。 What's the right (or better) way to do this?这样做的正确(或更好)方法是什么?

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()

Edit 1: This question is not about where to put the type annotations but how to ensure code-completion works in this context.编辑 1:这个问题不是关于在哪里放置类型注释,而是如何确保代码完成在这种情况下工作。 If the following line is commented-out...如果以下行被注释掉...

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

...the code will still run because of duck-typing but code-completion will not appear for .paddle() and when manually entered PyCharm code inspection will report: Unresolved attribute reference 'paddle' for class 'Leg'. ...由于鸭子输入,代码仍将运行,但 .paddle() 不会出现代码完成,当手动输入 PyCharm 代码检查将报告:未解析的属性引用 'Leg' 类的属性引用 'paddle'。

Not sure if this actually solves your problem but I think it's cleaner than what you propose:不确定这是否真的解决了您的问题,但我认为它比您提出的更清晰:

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__()

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

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