首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >在Python类中存储和断言类型

在Python类中存储和断言类型
EN

Stack Overflow用户
提问于 2019-10-10 05:07:05
回答 1查看 1.1K关注 0票数 2

PyCharm CE 2019.2.3警告我注意一个类,因为我存储数据的list和值数据type。我试图把它简化到本质上:

代码语言:javascript
运行
复制
class Data:
    def __init__(self, length, data_type):
        assert isinstance(length, int) and length >= 0
        assert isinstance(data_type, type)  # commenting this line out removes the warning
        self._data = [None] * length
        self._data_type = data_type

    def set_field(self, index, value):
        assert isinstance(value, self._data_type)  # commenting this line out removes the warning
        assert isinstance(index, int)
        self._data[index] = value

我在索引上得到警告:

意外类型:

(int,类型)

可能的类型:

(int,无)

(片,IterableNone)

检查信息:此检查检测函数调用表达式中的类型错误。由于动态分派和鸭类型,这在有限但有用的情况下是可能的。函数参数的类型可以在docstring或Python3函数注释中指定。

进一步评论意见:

删除两个标记断言中至少一个的

  • 移除警告

当那些断言指的是value时,对

  • 的警告出现在index中是相当令人困惑的

添加附加断言或类型提示的文档字符串的

  • 没有为me

删除警告。

我的问题:,我是不是做错了这种类型的存储和断言?是否有任何理由提出这一警告,如果没有,你认为有一个方便的方法来删除它吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-10-13 19:31:21

这里的问题有两个方面:

  • PyCharm在正确处理元类方面有一点盲点(在编写本报告时)。因此,如果没有额外的“提示”,它就无法推断出currently.
  • Because的正确类型,您用None PyCharm初始化了列表,将其视为包含Nones的列表。

让我们从元类问题开始:

您可以通过检查data_type是否是type (类的默认元类)的实例来检查它是否是类。然后检查value是否是该类的实例。这很好。

然而,PyCharm假设您的data_type是一个type (这是正确的),但是在isinstance(value, self._data_type)之后,它也假设value是一个type (这是不正确的--应该是_data_type类型)。因此,只要将assert isinstance(...)data_typevalue结合使用,PyCharm就无法推断出正确的value类型!

因此,这可能是PyCharm中的Bug或缺失特性,或者是PyCharm用来确定类型的库中的特性。

第二个问题是,通过使用_data初始化None,PyCharm将推断_data的类型为List[None] (包含Nones的列表)。

因此,如果PyCharm为value扣除除Any (可以分配给任何东西)或None (这是列表内容的预期类型)以外的任何其他内容,就会产生警告。

即使:

代码语言:javascript
运行
复制
    def set_field(self, index, value):
        assert isinstance(value, int)  # <-- difference
        assert isinstance(index, int)
        self._data[index] = value

警告会来的。

此时,您有两个选项:

  • 忽略警告,
  • 使用完整的类型提示(如果目标Python版本允许的话)。

如果您想使用类型提示,可以例如使用:

代码语言:javascript
运行
复制
from typing import List, Optional, TypeVar, Generic, Type

T = TypeVar('T')

class Data(Generic[T]):

    _data: List[Optional[T]]
    _data_type: Type[T]

    def __init__(self, length: int, data_type: Type[T]):
        self._data = [None] * length
        self._data_type = data_type

    def set_field(self, index: int, value: T):
        if isinstance(value, self._data_type):
            self._data[index] = value
        raise TypeError()

注意:我已经完全删除了断言。如果参数没有预期的类型或值,TypeErrorValueError将提供更多的信息。然而,在大多数情况下,文档和/或类型提示可以在Python中充分替代assertTypeError(至少使用IDE或使用mypy)。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/58315765

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档