Question about Sequence[str]

I have a function like this

def f(arg: Sequence[str]):
    if isinstance(arg, str):
        raise TypeError("arg should be a sequance of str, not str")
    for string in arg:
        print(string)

If a str value is passed to this function, an error would raise.
However, the IDE would not mark this as error. Because, str is a kind of Sequence[str] indeed.

Expected result:

f("dummy") # should get a type-hint warning

f(["aaa", "bbb"]) # should be ok

class MySequence(Sequence):
    ...

f(MySequence("aaa", "bbb")) # should be ok

So how shall I type-hint this argument to solve this problem?

It is not possible to create a type hint like “Type A except subtype B”. Your only option is to create a union of the types you do in fact support, and optionally alias it.

In your case, a Sequence can be one of list, tuple, str, range, bytes, bytearray or memoryview. The only Sequence[str] types that make sense are list[str] and tuple[str], so why not use list[str] | tuple[str]?

Edit: Sorry, I missed that you wanted to create your own Sequence type. In that case, create an alias for a union of list, tuple, and your own type:

SupportedSequence = list[str] | tuple[str] | MySequence[str]

def f(arg: SupportedSequence):

Note that tuple[str] means “a tuple of length 1, where the sole element is of type str”. You’ll usually want to use tuple[str, ...] (meaning “a tuple of arbitrary length, where all elements are of type str”) rather than tuple[str].

1 Like

TIL. Is the same true for list[str]?

No – tuple is a very special type in Python. See the “Annotating tuples” section of the typing docs for more details :slight_smile:

2 Likes