Type hinting mypy in list comprehension over duck-typed content

155 Views Asked by At

I have a (nested) list comprehension, and receive an error from mypy.

In my list comprehension, I am iterating over a list which is guaranteed to contain only instances of two types (that don't implement the same base; in the example below called A and B). The instances of both types are guaranteed to have the same attribute name which I utilize in the list comprehension. Mypy cannot automatically infer the type of the list, considers the content of the list mere objects (only common base), and thus warns, that the attribute name is not defined in instances of object.

I broke down my code into the following example:

from dataclasses import dataclass 
from typing import Union, Set, List

@dataclass
class A:
    name: str

@dataclass
class B:
    name: str

# Approach 1:
c: Union[A, B]
f : Set[str] = {c.name for c in [A('1'), B('2')]} # error: "object" has no attribute "name"  [attr-defined]


# Approach 2:
d: List[Union[A, B]] = [A('1'), B('2')]
g : Set[str] = {c.name for c in d} # No issue!

In approach 2, mypy is not reporting an error. Why is this the case, and why is the type hint for c in The approach 1 not sufficient?

Sadly, in my real use-case, the list d is only intermediate (does not have a name) and I cannot type hint like in approach 2. Is there a way to hint mypy that accessing name is actually viable without needing to transform the list comprehension into a loop?

I am using python3.8.

0

There are 0 best solutions below