【问题标题】:How to typehint that an object of a class is also adhering to a Protocol in Python?如何在 Python 中键入一个类的对象也遵守协议?
【发布时间】:2022-01-05 12:04:38
【问题描述】:

我有一组类,我们称它们为FooBar,它们都继承自在当前范围之外(不是我)定义的基类Father。我已经定义了一个协议类DummyProtocol,它有一个函数do_something

class DummyProtocol(Protocol):
   def do_something(self):
      ...
   

class Foo(Father):
   def do_something(self):
      pass

class Bar(Father):
   def do_something(self):
      pass

我有一个函数create_instance

def create_dummy_and_father_instance(cls, *args, **kwargs):
    return cls(*args, **kwargs)

我想以某种方式输入提示,即 cls 被输入提示以接受 Father 类型的类,该类也实现了 DummyProtocol

所以我把函数改成这个,表示cls是继承自FatherDummyProtocol的类型

def create_dummy_and_father_instance(
    cls: Type[tuple[Father, DummyProtocol]], *args, **kwargs
):
    return cls(*args, **kwargs)

但我在mypy 中收到此错误:

Cannot instantiate type "Type[Tuple[Father, DummyProtocol]]"

【问题讨论】:

  • stackoverflow.com/a/62661785/14617085是你要找的这种吗??
  • @basicmojo 我不这么认为。我需要一个类型提示,表明一个对象在参数部分的基类旁边实现了任意数量的协议。更改类定义是我唯一的方法吗?
  • 在这里问,discord.gg/t4gsyP9EQ3,管理员 asotille 非常擅长打字提示

标签: python type-hinting mypy


【解决方案1】:

您可以定义第二个继承自父亲和协议的父亲类(另请参阅mypy: how to verify a type has multiple super classes):

class DummyProtocol(Protocol):

    def do_something(self):
        ...
    
class Father:
    pass
    
class Father2(Father, DummyProtocol):
    pass
    
class Foo(Father2):

    def do_something(self):
        pass
    
class Bar(Father2):

    def do_something(self):
        pass
    
class FooNot(Father):
    pass
    
def create_dummy_and_father_instance(
    cls: Type[Father2]
):
    return cls()
    
create_dummy_and_father_instance(Foo)
create_dummy_and_father_instance(Bar)
create_dummy_and_father_instance(FooNot)  # mypy error ok

【讨论】:

  • 但这不是违反协议的使用吗?协议只是关于静态类型提示,而不是运行时影响,不是吗?
  • 我认为不是。来自文档:“请注意,从现有协议继承不会自动将子类转换为协议 - 它只是创建一个常规(非协议)类或实现给定协议(或协议)的 ABC。协议基类必须如果您正在定义协议,请始终明确存在。”
  • 所以任何时候我需要确保某些东西已经实现了一个基类和一个协议,我必须派生一个子类?这确实不是最佳选择。
  • 实例没有问题,但类协议有一些限制。
猜你喜欢
  • 2022-08-21
  • 1970-01-01
  • 1970-01-01
  • 2022-12-18
  • 1970-01-01
  • 2014-08-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多