New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Consider special casing zip(*tuples) #5247
Comments
Or we could have an (internal) representation for a diversified list?
Somehow similar to TypedDict.
|
In this case we'd need an iterator over a tuple of items. For example, |
OK, got it.
|
Why isn't it a TupleType? I think that the concept of TupleType should have little to do with |
@elazarg An interesting idea! It's not strictly a tuple type since tuples support indexing with integers but this doesn't work with an iterator. However, we could perhaps add an extra check so that This would still need a plugin since there's no syntax for defining a type that is tuple-like but doesn't extend the |
Any news on this? For the moment I helped myself with this (limited) function. from typing import TypeVar, Iterable
T1 = TypeVar("T1")
T2 = TypeVar("T2")
T3 = TypeVar("T3")
T4 = TypeVar("T4")
T5 = TypeVar("T5")
@overload
def transpose(
iterable: Iterable[tuple[T1, T2, T3, T4, T5]], strict: bool = False
) -> tuple[Iterable[T1], Iterable[T2], Iterable[T3], Iterable[T4], Iterable[T5]]:
...
@overload
def transpose(
iterable: Iterable[tuple[T1, T2, T3, T4]], strict: bool = False
) -> tuple[Iterable[T1], Iterable[T2], Iterable[T3], Iterable[T4]]:
...
@overload
def transpose(
iterable: Iterable[tuple[T1, T2, T3]], strict: bool = False
) -> tuple[Iterable[T1], Iterable[T2], Iterable[T3]]:
...
@overload
def transpose(
iterable: Iterable[tuple[T1, T2]], strict: bool = False
) -> tuple[Iterable[T1], Iterable[T2]]:
...
def transpose(
iterable: (
Iterable[tuple[T1, T2]]
| Iterable[tuple[T1, T2, T3]]
| Iterable[tuple[T1, T2, T3, T4]]
| Iterable[tuple[T1, T2, T3, T4, T5]]
),
strict: bool = False,
) -> (
tuple[Iterable[T1], Iterable[T2]]
| tuple[Iterable[T1], Iterable[T2], Iterable[T3]]
| tuple[Iterable[T1], Iterable[T2], Iterable[T3], Iterable[T4]]
| tuple[Iterable[T1], Iterable[T2], Iterable[T3], Iterable[T4], Iterable[T5]]
):
"""
Transpose the elements of given iterable, type safe
Only a typed shortcut for zip(*iterable)
See https://github.com/python/mypy/issues/5247 for background
"""
return zip(*iterable, strict=strict) # type: ignore |
In case it's helpful to have a gist for this: mypy-play.net from __future__ import annotations
from typing_extensions import *
def is_even(value: int) -> bool:
return not (value % 2)
table = [(i, is_even(i), str(i)) for i in range(20)]
assert_type(table, List[Tuple[int, bool, str]])
numbers, evens, strs = zip(*table)
# we get... we hoped for...
# ─────────────── ────────────────
reveal_type(numbers) # Tuple[Any, ...] Tuple[int, ...]
reveal_type(evens) # Tuple[Any, ...] Tuple[bool, ...]
reveal_type(strs) # Tuple[Any, ...] Tuple[str, ...]
# these statements hold true at runtime:
assert numbers == tuple(range(20))
assert evens == tuple(is_even(i) for i in range(20))
assert strs == tuple(str(i) for i in range(20))
# these all fail today:
assert_type(numbers, Tuple[int, ...])
assert_type(numbers, Tuple[bool, ...])
assert_type(numbers, Tuple[str, ...]) |
This seems to be a somewhat common
zip
idiom:The inferred type for
zip(*a)
isIterator[Tuple[Any, ...]]
, which causes false negatives in multiple assignments like this:Maybe we could add a plugin feature that can provide more precise types for
zip(*a)
in a multiple assignment context somehow. For example, the inferred type in the above example could beTuple[Tuple[str, ...], Tuple[int, ...]]
instead ofIterator[...]
, but only in the context of a multiple assignment since elsewhere the inferred type is not safe to use.The text was updated successfully, but these errors were encountered: