[Tutor] Type annotation errors
boB Stepp
robertvstepp at gmail.com
Thu Jun 4 14:01:42 EDT 2020
Ah, Peter, you gave me the pieces I needed to put it all together (I
think.).
On Thu, Jun 04, 2020 at 10:10:41AM +0200, Peter Otten wrote:
>boB Stepp wrote:
>
>> ...I have pared down a larger function to just what seems
>> to be giving the type annotation complaint:
>>
>> def parse_csv(data_rows: List, has_headers: bool = True) -> List:
>> """Parse a CSV file into a list of records."""
>> data_rows_iter = iter(data_rows)
>> if has_headers:
>> headers = next(data_rows_iter)
>> records = []
>> for row in data_rows_iter:
>> if has_headers:
>> # Make a dictionary
>> record = dict(zip(headers, row))
>> else:
>> # Otherwise make a tuple
>> record = tuple(row)
>> records.append(record)
>>
>> return records
>>
>> The complaint is: test.py|19 col 22 error| Incompatible types in
>> assignment (expression has type "Tuple[Any, ...]", variable has type
>> "Dict[Any, Any]")
>Let me note that I do not have any experience with mypy.
>However, the following
>
>> if has_headers:
>> # Make a dictionary
>> record = dict(zip(headers, row))
>> else:
>> # Otherwise make a tuple
>> record = tuple(row)
>
>makes every user of classical statically typed languages cringe.
>What's the type of record after the above? It's either the type of
>
>dict(zip(headers, row))
>
>or the type of
>
>tuple(row)
>
>I don't know if mypy is not smart enough or just refuses to infer the type
>-- in any case you can help it with a declaration.
>The most generic would be
>
>record: Any
>
>but making a union from the types in the error message should work too.
>
>record: Union[Tuple[Any, ...], Dict[Any, Any]]
This is the key bit that made it all come together for me. I had annotated
the function's parameters and its return types, but did not try to "help"
mypy with declaring one of the intermediate identifiers. And you caused me
to remember that I am allowed to declare types of identifiers without
assignment. I added the following just after my function's docstring and
it resolved the issue:
record: Union[Tuple[Any, ...], Dict[str, Any]]
>There are other things that you may know about the types
>
>- all records of one function run will be either tuples or dicts, never a
> mixture
>- all iterables in the data_rows list should have the same "length"
>- the first item in the data_rows list should be an iterable of strings if
> has_headers is true
>
>where I have no idea how it might be explained to a type checker. I fear
>that a moderately clean typed soluton would require two separate functions
>
>parse_csv()
>parse_csv_with_headers()
The points you list above are ones I have already given some thought to,
wondering if I should build in some checks. But as the "real problem" I am
working with is part of a series of exercises I am waiting to see where
Beasley is taking this. So far he has been using an incremental approach
"improving" the ever growing and morphing program(s) as he introduces more
Python.
Beasley mentioned type annotations very briefly, but I have been applying
them throughout the course as that is one of my current points of learning
that I have set for myself.
>> BTW, the above function works.
>
>Hooray to Python's ducktyping ;)
Amen!
--
Wishing you only the best,
boB Stepp
More information about the Tutor
mailing list