Search code examples
pythonpython-typingmypy

Type annotating instance attributes: in init or body?


Let's consider the two following syntax variations:

class Foo:

    x: int

    def __init__(self, an_int: int):
        self.x = an_int

And

class Foo:

    def __init__(self, an_int: int):
        self.x = an_int

Apparently the following code raises a mypy error in both cases (which is expected):

obj = Foo(3)
obj.x.title()  # this is a str operation

But I really want to enforce the contract: I want to make it clear that x is an instance variable of every Foo object. So which syntax should be preferred, and why?


Solution

  • If you ever want to use Any, Union, or Optional for an instance variable you should annotate them:

    from typing import Union
    
    class Foo:
    
        x: Union[int, str]
    
        def __init__(self, an_int: int):
            self.x = an_int
    
        def setx(self, a_str: str):
            self.x = a_str
    

    Otherwise you can use whichever you think is easier to read. mypy will infer the type from __init__.