Search code examples
pythonclassvariablestyping

Python typing of class instance attributes as copies of input args


When using typing in Python is it enough to do:

class Something:
    def __init__(self, arg1: str, arg2: Union[str, int]):
        self.arg1 = arg1
        self.arg2 = arg2

Or should everything be typed? Does the following have advantages and is it coding convention?

class Something:
    def __init__(self, arg1: str, arg2: Union[str, int]):
        self.arg1: str = arg1
        self.arg2: Union[str, int] = arg2

Solution

  • This depends on how smart your type checker is, but I'd expect all current Python checkers to be able to infer from the first form what the types are for arg1 and arg2.

    Note that you are missing the return type annotation, -> None:

    class Something:
        def __init__(self, arg1: str, arg2: Union[str, int]) -> None:
            self.arg1 = arg1
            self.arg2 = arg2
    

    See, for example, the mypy documentation on Class basics:

    The mypy type checker detects if you are trying to access a missing attribute, which is a very common programming error. For this to work correctly, instance and class attributes must be defined or initialized within the class. Mypy infers the types of attributes:

    class A:
        def __init__(self, x: int) -> None:
            self.x = x  # Aha, attribute 'x' of type 'int'
    
    a = A(1)
    a.x = 2  # OK!
    a.y = 3  # Error: 'A' has no attribute 'y'
    

    (bold emphasis mine).

    I otherwise prefer to put instance attribute annotations at the class level, where they are more visible and so more easily read by other developers:

    class Something:
        arg1: str
        arg2: Union[str, int]
    
        def __init__(self, arg1: str, arg2: Union[str, int]) -> None:
            self.arg1 = arg1
            self.arg2 = arg2
    

    Here, that leads to having to repeat yourself, but you could consider using the dataclasses module to avoid that.