首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何以抑制Pylance警告的方式声明没有值的类变量

如何以抑制Pylance警告的方式声明没有值的类变量
EN

Stack Overflow用户
提问于 2022-05-25 20:35:08
回答 2查看 483关注 0票数 2

我喜欢Pylance (VS Code)中的打字机,但似乎必须在忽略Pylance警告和类变量声明的最佳实践之间做出选择。很多时候,类变量是使用类构造函数中的None类型初始化的,该变量将在以后设置。例如:

代码语言:javascript
复制
class Person:
    def __init__(self) -> None:
        self.name:str = None

    def setName(self, name:str) -> None:
        self.name = name

在这种情况下,Pylance在赋值self.name:str = None上给出了以下错误

代码语言:javascript
复制
Cannot assign member "name" for type "Person"
Expression of type "None" cannot be assigned to member "name" of class "Person"
Type "None" cannot be assigned to type "str"

是否有任何方法在构造函数中声明self.name,使其不需要值,并且Pylance是愉快的?

编辑:有几个人建议使用typing.Optional来抑制这种警告。但是,如果创建了另一个成员函数来返回self.name并保证它返回的是str实例,则会生成另一个Pylance错误。请参见以下示例:

代码语言:javascript
复制
class Person:
    def __init__(self) -> None:
        self._name:Optional[str] = None

    @property
    def name(self) -> str:
        return self._name

    @name.setter
    def name(self, name:str) -> None:
        self._name = name

在这种情况下,Pylance生成错误:

代码语言:javascript
复制
(variable) _name: str | None
Expression of type "str | None" cannot be assigned to return type "str"
Type "str | None" cannot be assigned to type "str"
Type "None" cannot be assigned to type "str"

理想情况下,在构造函数中最初以某种方式“分配”self._name的方式是,其唯一允许的类型是str,但没有给出任何值。这个是可能的吗?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2022-05-25 23:19:07

update:很明显,我认为它在您的情况下是行不通的,但这是“自然的事情”。

如果您对实例属性进行注释,并且不希望它们能够读取"None“或其他哨位值,则只需声明该属性及其注释即可。也就是说,不要尝试在__init__中填充一个值,而是在类主体中声明注释:

代码语言:javascript
复制
class Person:

    name: str

    # No need for this:
    # def __init__(self) -> None:
    #    self.name:str = None

    def setName(self, name:str) -> None:
        self.name = name

假设您由于任何原因需要使用无效值初始化它,则最初的答案适用于:

如果程序员比类型检查器更了解这种情况,那么我认为使用typing.cast是这样的:这是运行时的不操作,但它告诉静态检查器值cast实际上是该类型的,而不考虑以前的声明:

(要明确的是:不做这个:)

代码语言:javascript
复制
import typing as t

class Person:

    def __init__(self) -> None:
        self._name: t.Optional[str, None] = None

    @property
    def name(self) -> str:
        return t.cast(str, self._name)

    ...

然而,在写完这篇文章后,我意识到,"self._name“在这个时候可能实际上是 "None”。打字机可以通过遵循程序步骤进行一些状态检查,但不是以这样一种通用的方式尝试在设置instance.name之前读取它应该会导致运行时错误。

因此,如果调用该方法来准确地表达这一点,它的工作原理是工具可以遵循由isinstance保护的部分代码(如果需要比isinstance更复杂的检查,请查看typing.TypeGuard的文档)--我们感谢这些工具确保程序运行后不会出现很难调试的错误:

(,这是正确的方式)

代码语言:javascript
复制
import typing as t

class Person:

    def __init__(self) -> None:
        self._name: t.Optional[str, None] = None

    @property
    def name(self) -> str:
        if isinstance(name:=self._name, str):
            return name
        raise AttributeError()

    @name.setter
    def name(self, name:str) -> None:
        self._name = name
票数 4
EN

Stack Overflow用户

发布于 2022-05-25 20:39:23

您需要通过typing.Optional使其成为可选的

代码语言:javascript
复制
#!/usr/bin/env python
from typing import Optional


class Person:
    def __init__(self) -> None:
        self.name: Optional[str] = None

    def setName(self, name: str) -> None:
        self.name = name

Python 3.10+通过佩普604联合类型表达式1支持更简单的语法,例如:

代码语言:javascript
复制
    def __init__(self) -> None:
        self.name: str | None = None
票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/72383861

复制
相关文章

相似问题

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