Reputation: 7260
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.
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
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