user9608133
user9608133

Reputation:

Python 3.9+ typing.Collection vs tuple vs typing.Iterable

What is the difference and use cases of typing.Collection?

E.g.:

from typing import Collection, Iterable

foo: Collection[int] = (1, 2)
bar: Iterable[int] = (1, 2)
spam: tuple[int] = (1, 2)

As for me, all looks the same and I do not understand why not to use always list, tuple, etc. as type hints.

Upvotes: 18

Views: 11234

Answers (1)

Carcigenicate
Carcigenicate

Reputation: 45750

It depends on what the capabilities of the object you need are. The general advice I've followed regarding type specification is

Specify the most general type when taking input, and the most specific type when giving output

If you don't need a Tuple specifically, don't specify a Tuple. Unless you absolutely need a tuple, you'll make the caller's life more difficult by specifying Tuple because you'll force them to either ignore your hints, or convert between collections if they currently have, for example, a list instead of a tuple.

Here's an example:

def func(tup: ???):
    for n in tup:
        pass

The only thing tup is used for is iteration. That means, following the above advice, you should fill in ??? with Iterable. That way, the caller can give a tuple, list, or even a custom type of theirs. It doesn't matter since your code doesn't care about the type; only that the object is iterable.

Contrast that with something like:

def func(lst: ???):
    lst.append(1)
    lst[2] = 5

This requires more specific functionality; but is still more general than a list. append and __setitem__ are a part of the MutableSequence ABC, so I'd specify that.

I rarely specify concrete collection types when type hinting input. The vast majority of the time, specifying the narrow set of capabilities that you require of the object is easy. Also for tuples specifically, I only specify Tuple in the cases where I want the user to input a sequence of pairs or something similar. Say I have a function that accepts an iterable of pairs of numbers. I'd type hint that input as:

Iterable[Tuple[int, int]]

I use Tuple (or tuple now) because the size of the pairs should be fixed at exactly two. I could accept a list of numbers, but then I don't have any size "guarantees". If I require the elements to have exactly a size of two, specifying Tuple is the cleanest way to achieve that.

Reference this table, and pick the type that best represents the actions that you want to carry out on the object.

Upvotes: 31

Related Questions