pylance中的reportAttributeAccessIssue解释
我有一个这样的类:
class ProcessRunner:
def __init__(self, network: nn.Module) -> None:
self.network: nn.Module = network
def run(self, processes: List[Process]):
for process in processes:
process.network = self.network
self.network = process.update()
在函数 run
中,关于 self.network
和 process.update()
出现了以下错误:
Cannot assign member "network" for type "Process"
Type "Module | None" cannot be assigned to type "Module"
"None" is incompatible with "Module"PylancereportAttributeAccessIssue
还有
Cannot assign member "network" for type "ProcessRunner*"
"None" is incompatible with "Module"PylancereportAttributeAccessIssue
我觉得这些问题部分是因为我的协议类 Process
引起的,它看起来是这样的:
@runtime_checkable
class Process(Protocol):
network: nn.Module
def update(self, **kwargs):
...
但我完全不明白这里的问题是什么原因:
- 第二个问题可能是因为
update
方法没有返回网络。一个好的解决办法是让网络只属于ProcessRunner
类。那么在这种情况下,方法怎么才能访问它呢? - 我对第一个问题的原因毫无头绪。协议类和
ProcessRunner
类中的对象都是nn.Module
类型。那为什么不满足呢?或者这是因为第二个问题引起的?
1 个回答
1
主要问题在于,你把 process.update()
的结果赋值给了 self.network
,而这个结果被推测为 None
。
self.network
的类型应该是 Module
,而 None
显然不是同一种类型,所以出现了第一个错误:
Cannot assign member "network" for type "ProcessRunner*"
"None" is incompatible with "Module"
现在你把 None
赋值给了 self.network
,Pyright 就认为它的类型是 Module | None
。但是,Process.network
的类型是 Module
,因此又报了第二个错误:
Cannot assign member "network" for type "Process"
Type "Module | None" cannot be assigned to type "Module"
"None" is incompatible with "Module"
一个解决办法是明确指定类型:
@runtime_checkable
class Process(Protocol):
network: Module
def update(self, **kwargs: Any) -> Module:
...
如果 .update()
并不打算返回任何东西,那就不要把它的结果赋值给 self.network
:
def run(self, processes: list[Process]):
for process in processes:
process.network = self.network
process.update()
self.network = process.network
你也可以定义一个更方便的 Process
接口:
@runtime_checkable
class Process(Protocol):
def update(self, network: Module, **kwargs: Any) -> None:
...
class ProcessRunner:
def run(self, processes: list[Process]):
for process in processes:
process.update(self.network)