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

使用mypy在Python中强制合成

  •  0
  • Jivan  · 技术社区  · 2 年前

    假设我有一些代码,其中我希望类具有一些特性,如属性或方法,但我不想使用继承来实现这一点,而是更喜欢组合。

    我将如何强制执行作为参数接收的类/对象实际呈现这些特征?

    继承示例:

    from abc import ABC, abstractmethod
    
    class FooBase(ABC):
        @abstractmethod
        def do_stuff(self):
            pass
    
    class Foo(FooBase):
        def do_stuff(self):
            return 'hello'
    
    def some_function(obj: FooBase):
        print(obj.do_stuff())
    

    在上述示例中, some_function 正在强制(通过MyPy静态地)执行 obj 参数是的子类 FooBase .

    相反,我希望 some\u函数 强制执行(静态,通过MyPy) obj公司 有一个 do_stuff 方法,但不一定是 食品基地 .

    2 回复  |  直到 2 年前
        1
  •  2
  •   Samwise    2 年前

    使用 typing.Protocol :

    from typing import Protocol
    
    class Foo(Protocol):
        def do_stuff(self) -> str: ...
    
    class Bar:
        def do_stuff(self) -> str:
            return "hello"
    
    def some_function(obj: Foo):
        print(obj.do_stuff())
    
    
    some_function(Bar())  # ok
    

    之间的区别 Protocol ABC 您可以实现一个协议,而无需显式继承它 Bar 被视为 Foo mypy,尽管它不是 Foo公司 .

    如果传递的类型未实现协议,则会出现错误,例如:

    class Baz:
        def do_stuff(self) -> int:
            return 42
    
    some_function(Baz())  
    # error: Argument 1 to "some_function" has incompatible type "Baz"; expected "Foo"
    # note: Following member(s) of "Baz" have conflicts:
    # note:     Expected:
    # note:         def do_stuff(self) -> str
    # note:     Got:
    # note:         def do_stuff(self) -> int
    
    推荐文章