如何在 Python 中对对象的属性执行类型保护

Mig*_*dge 11 python python-typing typeguards

PEP 647引入了类型防护来使用函数执行复杂的类型缩小操作。如果我有一个属性可以具有各种类型的类,是否有一种方法可以对作为函数参数给出的对象的属性执行类似的类型缩小操作?

class MyClass:
    """
    If `a` is `None` then `b` is `str`
    """
    a: Optional[int]
    b: Optional[str]
    # Some other things

def someTypeGuard(my_obj: MyClass) -> ???:
    return my_obj.a is not None
Run Code Online (Sandbox Code Playgroud)

我想我可能有必要在类型提示中实现一些与方括号有关的东西,但我真的不知道从哪里开始。

Mig*_*dge 9

TypeGuard注释可用于注释类的子类。如果为这些类指定了参数类型,那么 MyPy 将成功识别类型缩小操作。

class MyClass:
    a: Optional[int]
    b: Optional[str]
    # Some other things

# Two hidden classes for the different types
class _MyClassInt(MyClass):
    a: int
    b: None
class _MyClassStr(MyClass):
    a: None
    b: str


def someTypeGuard(my_obj: MyClass) -> TypeGuard[_MyClassInt]:
    """Check if my_obj's `a` property is NOT `None`"""
    return my_obj.a is not None

def someOtherTypeGuard(my_obj: MyClass) -> TypeGuard[_MyClassStr]:
    """Check if my_obj's `b` property is NOT `None`"""
    return my_obj.b is not None
Run Code Online (Sandbox Code Playgroud)

assert someOtherTypeGuard(obj)遗憾的是,未能缩小到一种类型并不会自动缩小到另一种类型,而且除了在 else 块中之外,我找不到一种简单的方法来做到这一点。

即便如此,这似乎仍然是最好的解决方案。