'Python type hint instance attribute with module not instantiated

Suppose we have the following class.

from docxtpl import DocxTemplate
from abc import ABC, abstractmethod
from typing import Dict, Any, Union


class MyClass(ABC):

    def __init__(self, name: str, filename: Union[str, PathLike]) -> None:
        """ Constructor """
        self.name = name
        self.filename = filename
        self.template: DocxTemplate

    def f1(self) -> None:
        self.template = DocxTemplate(filename)

I want to type self.template as DocxTemplate but instantiate it later dynamically, in f1. The point is that I am getting a warning in f1 that says:

Instance attribute template defined outside __init__

I don't really know why. I also tried to type self.template as follows:

self.template: Optional[DocxTemplate] = None

But this forces my to check the existence of self.template in some parts of my code.

What point am I not understanding? How should it be correct?

Thanks and greetings!



Solution 1:[1]

You could try making self.template a property instead of an attribute:

from docxtpl import DocxTemplate
from abc import ABC, abstractmethod
from typing import Dict, Any, Union
import os


class MyClass(ABC):

    def __init__(self, name: str, filename: Union[str, os.PathLike]) -> None:
        """ Constructor """
        self.name = name
        self.filename = filename
        self.__template = None
        
    @property
    def template(self) -> DocxTemplate:
        return self.__template

    @template.setter
    def template(self, value: DocxTemplate) -> None:
        self.__template = value
        return
    
    @template.deleter
    def template(self) -> None:
        self.__template = None
        return

    def f1(self) -> None:
        self.template = DocxTemplate(self.filename)

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 David Camp