【问题标题】:Python Protocol Allowing Optional Attributes允许可选属性的 Python 协议
【发布时间】:2021-10-02 08:36:06
【问题描述】:

假设我有一个协议Foo

from typing import Protocol, Optional


class Foo(Protocol):
    val: Optional[int]

还有一个类似下面的函数:

def func(obj: Foo) -> None:
    if obj.val is not None:
        print(obj.val)

我希望ImplAImplB(如下所示)应该是func 可接受的参数,因为val: intval: Optional[int] 更具体。

class ImplA:
    val: int


class ImplB:
    val: Optional[int]

a = ImplA()
b = ImplB()

func(a)  # It works
func(b)  # Argument 1 to "func" has incompatible type "ImplB"; expected "Foo"

由于它不起作用,我必须定义 Bar 并取两个类的并集。但是,有没有办法构造一个协议,使得val: Optional[int]val: int 在没有Union 的情况下都被接受?

class Bar(Protocol):
    val: int

def func(obj: Union[Foo, Bar]): ...

编辑:

为此,我们需要确保 val 的类型是协变的。就我现在所见,Protocol 似乎将其定义为不变量。这样就无法达到我的要求了吗?

【问题讨论】:

    标签: python protocols type-hinting python-typing duck-typing


    【解决方案1】:

    我运行了您的代码,但它对 func(a) 和 func(b) 都提出了错误。该错误与

    有关

    if obj.val is not none:

    因为没有一个对象具有属性“val”。我用 Python 3.9.9 测试了代码。

    我修改了该子句以测试对象是否具有属性 val,希望这会有所帮助。

    from typing import Protocol, Optional
    
    
    class Foo(Protocol):
        val: Optional[int]
    
    
    def func(obj: Foo) -> None:
        if hasattr(obj, 'val'):
            print(obj.val)
        else:
            print(f"{obj} variable val is undefined")
    
    
    class ImplA:
        val: int
    
    
    class ImplB:
        val: Optional[int]
    
    
    print("Accessing func with ImplA and ImplB before initializing val")
    a = ImplA()
    b = ImplB()
    func(a)
    func(b)
    
    print("Accessing func with ImplA and ImplB after initializing val")
    a = ImplA()
    a.val = 2
    b = ImplB()
    b.val = 20
    func(a)
    func(b)
    
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-04-06
      • 1970-01-01
      • 1970-01-01
      • 2018-12-31
      • 2018-10-30
      • 2021-10-05
      • 1970-01-01
      相关资源
      最近更新 更多