【问题标题】:Type annotation with multiple types in **kwargs**kwargs 中具有多种类型的类型注释
【发布时间】:2017-11-03 23:02:32
【问题描述】:

我正在尝试将 Python 的 type annotations 与抽象类一起使用。 我的__init__ 函数如下所示:

from abc import ABCMeta

class SomeClass(object, metaclass=ABCMeta):
    def __init__(self, *args, **kwargs):
        print("Initiating %s object.", self.__class__.__name__)

        self.username = kwargs['data']
        assert isinstance(self.username, str)

        is_premioum = kwargs.get('premioum', False)

        self.money_investmant = kwargs.get('investmant')
        if isinstance(self.money_investmant, str):
            self.money_investmant = float(self.money_investmant)

如您所见,kwargs 可以包含来自多种类型的参数 - floatboolstr

现在,我正在尝试为函数编写类型注释,如下所示:

def __init__(self, *args, **kwargs: Union[bool, str, float]) -> None:

但是我的PyCharm IDE 提醒我:

除了类型 'Integral',改为使用 'str'

还有:

在 bool | 中找不到引用“get”字符串 |浮动'

我做错了吗?

如果kwargs包含多种类型的参数,我应该如何编写类型注释?

【问题讨论】:

    标签: python python-3.x type-hinting typing keyword-argument


    【解决方案1】:

    请参阅 PyCharm 问题跟踪器上的 this bugthis bug。这显然是 PyCharm 检查器的问题; mypy(Python 的另一个类型检查器)在我执行类似代码时不会抱怨

    已经有一个解决方案,它显然是可用的in build 171.2014.23。在那之前,我认为Any 足以作为临时解决方法让检查员停止抱怨。

    【讨论】:

      【解决方案2】:

      如果想要描述 kwargs 中预期的特定命名参数,可以改为传入定义必需和可选参数的 TypedDict。可选参数是 kwargs:

      这允许一个人有未设置的(不是默认的)可选参数并且有类型提示。

      如果它们的键具有无效的 python 变量名,这也很有用,因为除了非常一般的 **kwargs 值类型提示之外,TypedDict 是定义这些值的类型的唯一方法。

      import typing
      from abc import ABCMeta
      
      
      class RequiredProps(typing.TypedDict):
          # all of these must be present
          data: str
      
      class OptionalProps(typing.TypedDict, total=False):
          # these can be included or they can be omitted
          premium: bool
          investment: typing.Union[str, float]
      
      class ReqAndOptional(RequiredProps, OptionalProps):
          pass
      
      class SomeClass(object, metaclass=ABCMeta):
          def __init__(self, *args, kwargs: ReqAndOptional):
              print("Initiating %s object.", self.__class__.__name__)
      
              self.username = kwargs['data']
              assert isinstance(self.username, str)
      
              is_premium = kwargs.get('premium', False)
              assert isinstance(is_premium, bool)
      
              self.money_investment = kwargs.get('investment')
              assert isinstance(elf.money_investment, (str, float))
              if isinstance(self.money_investment, str):
                  self.money_investment = float(self.money_investment)
      

      【讨论】:

      • 为了支持一个真正常见的模式,这不是过多的样板代码吗?
      • 是的,它有点像样板文件。优点是一根手杖具有未设置的带有类型提示的可选参数。如果使用普通的 kwargs,则缺少它们的类型提示。如果 ne 使用 None 默认值,则在可能不想这样做时加载 None 值。
      • 是否可以在__init__ 中使用**kwargs 而不是kwargs
      • 刚刚用pycharm检查了这个,答案是否定的。当为 **kwargs pycharm 添加类型提示时,至少假设您定义的是值的类型而不是总字典,请阅读stackoverflow.com/a/63550734/4175822
      猜你喜欢
      • 2016-08-30
      • 1970-01-01
      • 2017-10-02
      • 2020-08-17
      • 1970-01-01
      • 2016-10-26
      • 1970-01-01
      • 2019-04-13
      • 1970-01-01
      相关资源
      最近更新 更多