HTF
HTF

Reputation: 7260

Default vs optional function parameters with type hints

So the function gendata accepts two optional parameters (name and source) and then based on the value of source invokes parser with the same parameters that are however required in this function.

  1. What is the recommended way to solve the required vs. none required parameters?
  2. There is an example in Python docs for typing.Types and it shows that Type[SuperClass] should accept all child classes that inherit from it. Why mypy complains in this case and why only for arg 1 and 2 but not 3 (source)?

exmaple.py:

from dataclasses import dataclass
from typing import List, Optional, Type


@dataclass
class BaseItem:
    name: str
    value: int


@dataclass
class Item(BaseItem):
    pass


@dataclass
class AnotherItem(BaseItem):
    pass


def parser(item: Type[BaseItem], name: str, source: int) -> Type[BaseItem]:
    item.value = source
    return item


def gendata(
    items: List[Item], name: Optional[str] = None, source: Optional[int] = None
) -> None:
    for item in items:
        if source:
            item = parser(item, name, source)

Testing:

$ mypy example.py 
e.py:31: error: Incompatible types in assignment (expression has type "Type[BaseItem]", variable has type "Item")
e.py:31: error: Argument 1 to "parser" has incompatible type "Item"; expected "Type[BaseItem]"
e.py:31: error: Argument 2 to "parser" has incompatible type "Optional[str]"; expected "str"
Found 3 errors in 1 file (checked 1 source file)

Upvotes: 5

Views: 7050

Answers (1)

Elton Viana
Elton Viana

Reputation: 301

First thing, about the Type[Something] errors, according to the documentation, you should use Type[Something] when you're receiving the type as parameter, if you're receiving an instance of BaseItem, you should just use BaseItem.

Example:

a = 3         # Has type 'int'
b = int       # Has type 'Type[int]'
c = type(a)   # Also has type 'Type[int]'

Reference: https://docs.python.org/3/library/typing.html#typing.Type


About the Optional error, I usually read optional as nullable (in the documentation they even say Optional[X] is equivalent to Union[X, None].

Reference: https://docs.python.org/3/library/typing.html#typing.Optional

So if you're receiving a parameter with type Optional[str] and try to pass to a function that receives a str, this will raise an error, one solution is just check if the value is None and put a default string instead, like:

def gendata(
    items: List[Item], name: Optional[str] = None, source: Optional[int] = None
) -> None:
    if name is None:
        name = ''
    if source:
        for item in items:
            item = parser(item, name, source)

Upvotes: 5

Related Questions