pylance中的reportAttributeAccessIssue解释

0 投票
1 回答
275 浏览
提问于 2025-04-14 18:24

我有一个这样的类:

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.networkprocess.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):
        ...

但我完全不明白这里的问题是什么原因:

  1. 第二个问题可能是因为 update 方法没有返回网络。一个好的解决办法是让网络只属于 ProcessRunner 类。那么在这种情况下,方法怎么才能访问它呢?
  2. 我对第一个问题的原因毫无头绪。协议类和 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"

一个解决办法是明确指定类型:

(playground link)

@runtime_checkable
class Process(Protocol):
    network: Module

    def update(self, **kwargs: Any) -> Module:
        ...

如果 .update() 并不打算返回任何东西,那就不要把它的结果赋值给 self.network

(playground link)

    def run(self, processes: list[Process]):
        for process in processes:
            process.network = self.network
            process.update()
            self.network = process.network

你也可以定义一个更方便的 Process 接口:

(playground link)

@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)

撰写回答