skip to Main Content

I’m attempting to write a generic class in Python 3.11 that should be able to process a list of elements using different processing classes (A or B in this example). My goal is to use the type variable T to specify the processing class that should be used.

Clarification: Each element x within the list Xrequires an individual initialization of the subclass A or B, so initializing is only possible withing the process() method.

Here’s my code:

from typing import List, Self, TypeVar, Generic

class A:
    def __init__(self):
        pass

    def process(self, x):
        return x + 1

class B:
    def __init__(self):
        pass

    def process(self, x):
        return x + 2

T = TypeVar("T", A, B)

class ListProcessor(Generic[T]):
    """Apply a Transformer to the individual list elements."""

    def __init__(self, processor: T):
        self.processor_class = processor
        self.processors: List[T] = []  # <- Pylance complains! see error message (1)

    def process(self, X) -> List:
        x_processed = []
        for x in X:
            proc: T = self.processor_class()  # <- Pylance complains! see error message (2)
            result = proc.process(x)
            x_processed.append(result)
            self.processors.append(proc)
        return x_processed

lp = ListProcessor(B)
lp.process([1, 2, 3])

The output of the above is:

[3, 4, 5]

which is what I expect. But while the code runs, Pylance type checker complains in VSCode.

  1. For the line self.processors: List[T] = [], I get:

    Variable not allowed in type expression PylancereportGeneralTypeIssues
    T: ~T
    (constant) T: Unknown

  2. For the line proc: T = self.processor_class(), I get:

    Object of type "A*" is not callablePylancereportGeneralTypeIssues
    Object of type "B*" is not callablePylancereportGeneralTypeIssues

I’m struggling to understand these error messages. Could someone help clarify why these errors occur and how I can fix them?

2

Answers


  1. The line self.processors: List[T] = [] should be self.processors: List[T] = [] because self.processors is a list that will contain instances of type T.

    The line proc: T = self.processor_class() should be proc: T = self.processor_class because we are assigning the class itself, not an instance of the class.

    Finnaly, in the line, lp = ListProcessor(B), you need to instantiate the B class by using B() because you want to pass an instance of class B to the ListProcessor constructor.

    Login or Signup to reply.
  2. Inded I totaly miss read self.processors: List[T] = [], sorry :’)
    Though it seems like vscode is not complaining about anything here, I think changing the processor: T by processor: Type[T] and the process function to proc: T = self.processor_class() to proc = self.processor_type() should do the job.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search