如何以与静态类型检查兼容的方式实现接口?

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

我有两个基类FooBar,还有一个Worker类,它期望对象的行为类似于Foo。然后,我添加了另一个类,该类实现了Foo中的所有相关属性和方法,但是我没有设法通过mypy将其成功传递给静态类型检查。这是一个小例子:

class MyMeta(type):
    pass

class Bar(metaclass=MyMeta):
    def bar(self):
        pass

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

    def foo(self):
        pass

class Worker:
    def __init__(self, obj: Foo):
        self.x = obj.x

此处Worker实际上接受任何Foo类对象,即具有属性x和方法foo的对象。因此,如果obj走路像Foo,并且发出嘎嘎声,则Foo会很高兴。现在,整个项目都使用类型提示,因此目前我指示Worker。到目前为止一切顺利。

[现在还有另一个类obj: Foo,它继承了FooBar的行为类似于Bar,但是它不能成为Foo的子类,因为它通过属性公开了其属性(因此Foo参数没有意义) ):

__init__

此时,class FooBar(Bar): """Objects of this type are bar and they are foo-ish.""" @property def x(self) -> int: return 0 def foo(self): pass 显然会导致类型检查器错误:

Worker(FooBar())

使用抽象基类

为了将error: Argument 1 to "Worker" has incompatible type "FooBar"; expected "Foo" -ish的接口传达给类型检查器,我想到了为Foo -ish类型创建抽象基类:

Foo

但是我无法使import abc class Fooish(abc.ABC): x : int @abc.abstractmethod def foo(self) -> int: raise NotImplementedError 继承自FooBar,因为Fooish有其自己的元类,因此这会引起元类冲突。因此,我考虑过在BarFooish.register上同时使用Foo,但是mypy并不同意:

FooBar

哪个会产生以下错误:

@Fooish.register
class Foo:
    ...

@Fooish.register
class FooBar(Bar):
    ...

class Worker:
    def __init__(self, obj: Fooish):
        self.x = obj.x

使用“普通”类作为接口

我考虑的下一个选项是创建一个接口,而不以“常规”类的形式从error: Argument 1 to "Worker" has incompatible type "Foo"; expected "Fooish" error: Argument 1 to "Worker" has incompatible type "FooBar"; expected "Fooish" 继承,然后使abc.ABCFoo都继承自该接口:

FooBar

现在mypy并没有抱怨class Fooish: x : int def foo(self) -> int: raise NotImplementedError class Foo(Fooish): ... class FooBar(Bar, Fooish): ... class Worker: def __init__(self, obj: Fooish): self.x = obj.x 的参数类型,而是抱怨Worker.__init__(它是FooBar.x)与property的签名不兼容:

Fooish.x

而且error: Signature of "x" incompatible with supertype "Fooish" (抽象)基类现在可以实例化,并且是Fooish的有效参数,尽管它没有意义,因为它不提供属性Worker(...)

问题...

现在,我陷入了一个问题,即如何在不使用继承的情况下将该接口与类型检查器进行通信(由于元类冲突;即使有可能,mypy仍会抱怨x的签名不兼容)。有办法吗?

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

据我所知,您可能可以添加一个x,基本上可以允许Union

Foo or Bar or Fooish
© www.soinside.com 2019 - 2024. All rights reserved.