I have following class
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()
Which shows in function run
for self.network
and process.update()
following Errors:
Cannot assign member "network" for type "Process"
Type "Module | None" cannot be assigned to type "Module"
"None" is incompatible with "Module"PylancereportAttributeAccessIssue
and
Cannot assign member "network" for type "ProcessRunner*"
"None" is incompatible with "Module"PylancereportAttributeAccessIssue
I think I understand that those issues a are partial coming from my Protocol Class Process
, which looks like this:
@runtime_checkable
class Process(Protocol):
network: nn.Module
def update(self, **kwargs):
...
But I do not understand completely what causes the issue here:
update
method doesn't return the network here. Okay solution could be that the network is only part of the ProcessRunner
class. But how can a method access it in this case?ProcessRunner
class are both of type nn.Module
. Why is it not satisfied then? or is this an issue which appears by the second issue?The main problem is that you are assigning the result of process.update()
to self.network
, which is inferred to be None
.
self.network
has the type of, as you would expect, Module
. None
clearly isn't of the same type, hence the first error:
Cannot assign member "network" for type "ProcessRunner*"
"None" is incompatible with "Module"
Now that you have assigned None
to self.network
, Pyright thinks that it is of type Module | None
. However, Process.network
is of type Module
, so a second error is reported:
Cannot assign member "network" for type "Process"
Type "Module | None" cannot be assigned to type "Module"
"None" is incompatible with "Module"
One solution is to explicitly specify the types:
@runtime_checkable
class Process(Protocol):
network: Module
def update(self, **kwargs: Any) -> Module:
...
If .update()
is not intended to return anything, then don't assign that to self.network
:
def run(self, processes: list[Process]):
for process in processes:
process.network = self.network
process.update()
self.network = process.network
You could also define a more ergonomic Process
interface:
@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)