首页 > 解决方案 > 动态定义的实例属性应该如何与类型提示/linting 一起使用?

问题描述

考虑下面的代码,我的类Child继承自Parent(一个来自第三方包的类,我无法控制)。Parent有一个内置方法set_attributes,用于向实例添加任意属性:

# third-party code, I can't modify this
class Parent:
    def __init__(self, a: str) -> None:
        self.a = a

    def set_attributes(self, **kwargs) -> None:
        for k, v in kwargs.items():
            setattr(self, k, v)


# my code, I can modify this
class Child(Parent):
    def __init__(self, a: str, b: int, c: float) -> None:
        super().__init__(a=a)
        self.set_attributes(b=b, c=c)

    def show_attributes(self):
        print(self.a)
        print(self.b)
        print(self.c)

这很好用,但是任何 linter 都会在该show_attributes方法上给我一个警告,告诉我self.b并且self.c不存在(因为它们是在运行时定义的,当self.set_attributes(b=b, c=c)执行该行时)。

克服此限制的一种方法是为 中的属性定义一个占位符Child.__init__

from typing import Optional

class Child(Parent):
    def __init__(self, a: str, b: int, c: float) -> None:
        super().__init__(a=a)
        self.b: Optional[int] = None
        self.c: Optional[float] = None
        self.set_attributes(b=b, c=c)

...但现在的问题是,它self.bself.c应该是真正的价值观None——它只是一个占位符。我不希望我的 linter 考虑这些值可能None适用于我的其余代码的可能性,因为它们不应该是。

我考虑过的其他选择是:

class Child(Parent):
    def __init__(self, a: str, b: int, c: float) -> None:
        super().__init__(a=a)
        self.b: int = None
        self.c: float = None
        self.set_attributes(b=b, c=c)
class Child(Parent):
    def __init__(self, a: str, b: int, c: float) -> None:
        super().__init__(a=a)
        self.b: int = 0
        self.c: float = 0.0
        self.set_attributes(b=b, c=c)
class Child(Parent):
    def __init__(self, a: str, b: int, c: float) -> None:
        super().__init__(a=a)
        self.b: int
        self.c: float
        self.set_attributes(b=b, c=c)

这些解决方案都没有让我非常满意。set_attributes此外,如果我决定通过添加**kwargs来保持灵活性,这些解决方案都不起作用Child.__init__,即:

class Child(Parent):
    def __init__(self, a: str, b: int, c: float, **kwargs) -> None:
        super().__init__(a=a)
        self.b: int
        self.c: float
        self.set_attributes(b=b, c=c, **kwargs)

有没有更好的方法来解决这个问题,或者这只是我必须习惯的限制?

标签: pythoninheritancestatic-analysistype-hinting

解决方案


推荐阅读