pythonpython-typingpytype

Type annotations for factory method


Suppose I have a class method that serves as a factory:

class Foo:

  def __init__(self, text):
    self.text = text

  @classmethod
  def from_file(cls, path):
    with open(path, 'rt') as f:
      return cls(f.read())


class Bar(Foo):
  
  def lines(self):
    return self.text.count('\n')


print(Bar.from_file('bar.txt').lines())

Now I want to add pytype annotations to this. What annotations should I use for the from_file class method? Just marking it as -> 'Foo' doesn't capture the more specific type known in case of a derived class like Bar. So the expression in the print call won't know it's a Bar and has lines. How do I express that the result will be an instance of argument cls?


Solution

  • You can use a type variable for this.

    from typing import Type, TypeVar
    
    
    FooType = TypeVar('FooType', bound='Foo')
    
    
    class Foo:
    
      text: str
    
      def __init__(self, text: str):
        self.text = text
    
      @classmethod
      def from_file(cls: Type[FooType], path: str) -> FooType:
        with open(path, 'rt') as f:
          return cls(f.read())
    
    
    class Bar(Foo):
    
      def lines(self) -> int:
        return self.text.count('\n')
    
    
    print(Bar.from_file('bar.txt').lines())