Search code examples
pythonpython-typingmypy

Should Typing.Optional be used if the default value of the parameter is not None?


So I know the standard use case of Typing.Optional, which means it is a union between the type and None. E.g.

def my_func(a, b=None):
  # type: (str, Typing.Optional[str]) -> str
  # do stuff with the strings

But what if the default value for B is an actual string?

def my_func(a, b='hello'):

Should the type of b be Optional[str] or just str? Because it is optional from the perspective of the user because you aren't required to pass a value when calling this function, but that doesn't mean None should work though. Mypy doesn't seem to detect a problem with either one.


Solution

  • An argument having the type Optional[...] is not about whether the user has to specify it or not, but rather whether the function must account for the argument being potentially None. Given this example:

    def my_func(a, b='hello'):
       pass
    

    b will be inferred as str because b, even if not provided by the caller, will have a non-None value. As such, attempting to override the default with None like this:

    my_func(..., None)
    

    would result in a MyPy error.

    Note that I didn't say that b can't be explicitly annotated as Optional[str]. This is fine:

    def my_func(a, b: Optional[str] = 'hello'):
       pass
    

    b can be annotated as Optional[str] here because b's default is str, and Optional[str] is a superset of str. Like you pinpointed, Optional[str] is str union None.

    This enables the caller to explicitly pass None like this:

    my_func(..., None)