我喜欢Pylance (VS Code)中的打字机,但似乎必须在忽略Pylance警告和类变量声明的最佳实践之间做出选择。很多时候,类变量是使用类构造函数中的None类型初始化的,该变量将在以后设置。例如:
class Person:
def __init__(self) -> None:
self.name:str = None
def setName(self, name:str) -> None:
self.name = name在这种情况下,Pylance在赋值self.name:str = None上给出了以下错误
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错误。请参见以下示例:
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生成错误:
(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,但没有给出任何值。这个是可能的吗?
发布于 2022-05-25 23:19:07
update:很明显,我认为它在您的情况下是行不通的,但这是“自然的事情”。
如果您对实例属性进行注释,并且不希望它们能够读取"None“或其他哨位值,则只需声明该属性及其注释即可。也就是说,不要尝试在__init__中填充一个值,而是在类主体中声明注释:
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实际上是该类型的,而不考虑以前的声明:
(要明确的是:不做这个:)
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的文档)--我们感谢这些工具确保程序运行后不会出现很难调试的错误:
(,,这是正确的方式)
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发布于 2022-05-25 20:39:23
您需要通过typing.Optional使其成为可选的
#!/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 = namePython 3.10+通过佩普604的联合类型表达式1支持更简单的语法,例如:
def __init__(self) -> None:
self.name: str | None = Nonehttps://stackoverflow.com/questions/72383861
复制相似问题