Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python type annotation for sequences of strings, but not for strings?

Is there a Python type hint that matches lists, tuples and possibly other sequential types, but does not match strings?

The issue is that strings are at the same time sequences of strings of length 1 (e.g. individual characters), so they technically match the Sequence[str], but providing a string to a function expecting a list of strings is an error in maybe 100% cases.

Is there a way to exclude strings from type annotation to make it something similar to non-existent And[Sequence[str], Not[str]]?

As for the purpose, I would like to annotate this function:

PathType = Union[str, os.PathLike]
def escape_cmdline(argv: Union[List[PathType], Tuple[PathType]]) -> str: ...

But existing signature looks bloated to me, and does not cover any custom types that are list and tuple compatible. Is there any better way?

like image 883
toriningen Avatar asked Jul 04 '17 18:07

toriningen


People also ask

What is sequence string in Python?

In Python programming, sequences are a generic term for an ordered set which means that the order in which we input the items will be the same when we access them. Python supports six different types of sequences. These are strings, lists, tuples, byte sequences, byte arrays, and range objects.

What is union type in Python?

Union type; Union[X, Y] is equivalent to X | Y and means either X or Y. To define a union, use e.g. Union[int, str] or the shorthand int | str . Using that shorthand is recommended.

What is type annotation in Python?

Type annotations — also known as type signatures — are used to indicate the datatypes of variables and input/outputs of functions and methods. In many languages, datatypes are explicitly stated. In these languages, if you don't declare your datatype — the code will not run.

How do you use type hints in Python?

Here's how you can add type hints to our function: Add a colon and a data type after each function parameter. Add an arrow ( -> ) and a data type after the function to specify the return data type.


2 Answers

Apparently, this is not possible with type hints. PEP 484 can not distinguish between Sequence[str], Iterable[str] and str according to Guido van Rossum.

Source: https://github.com/python/mypy/issues/1965 and https://github.com/python/typing/issues/256

like image 185
MacFreek Avatar answered Oct 13 '22 11:10

MacFreek


I couldn't find anything about the type exclusion or the type negation, seems like it's not supported in current version of Python 3. So the only distinctive feature of strings that crossed my mind is that strings are immutable. Maybe it'll help:

from typing import Union
from collections.abc import MutableSequence


MySequenceType = Union[MutableSequence, tuple, set]
def foo(a: MySequenceType):
    pass

foo(["09485", "kfjg", "kfjg"]) # passed
foo(("09485", "kfjg", "kfjg")) # passed
foo({"09485", "kfjg", "kfjg"}) # passed
foo("qwerty") # not passed
like image 4
Tsagana Nokhaeva Avatar answered Oct 13 '22 11:10

Tsagana Nokhaeva