Mattwmaster58
Mattwmaster58

Reputation: 2576

Type hinting a non-generator (non-consumable) iterable

I'd like to type hint a function like this:

from types import Iterable

def func(thing: Iterable[str]) -> None:
    for i in range(10):
        for x in thing:
            do_thing(x)

PyCharm will (correctly) let me get away with passing in a generator to this function, but I want to type hint it in a way that it won't allow me to, while still accepting other iterables.

Using Sequence[str] isn't an option, iterables like KeyView aren't sequences, but I would still like to be able to include them.

Someone mentioned using a Union with a Sequence + KeyView, which would work, but I was wondering if there was a more elegant and universal solution

Of course, I could just convert thing to a list no matter what, but I'd rather just have this function type hinted correctly.

Using Python 3.7

Upvotes: 10

Views: 749

Answers (2)

Yohann
Yohann

Reputation: 150

I know this dos not directly respond to the question, but one solution might be to turn the problem the other way around:

How do i iterate over a potentially consumable iterable more than one time:

from itertools import tee
from types import Iterable


def func(thing: Iterable[str]) -> None:
    reps=10
    iterables = tee(thing, reps)
    for i in range(reps):
        for x in iterables[i]:
            do_thing(x)

Upvotes: 0

Felix Schwarz
Felix Schwarz

Reputation: 3078

Unfortunately I think this is just not possible with Python's type system.

Straight from Guido (source):

Our type system doesn't allow you to express that -- it's like asking for any Animal except Cat. Adding an "except" clause like that to the type system would be a very difficult operation.

Since there's no solution, I'm going to close this as "won't fix".

His suggestion:

Yeah, the practical solution is Sequence|Set|Mapping. The needed negation is years off.

Upvotes: 3

Related Questions