Brief introduction to typing in Python

Skip ahead if you know what structural typing, nominal typing and duck typing are.

I think much of the confusion arises from the fact that typing was a provisional module between versions 3.5 and 3.6. And was still subject to change between versions 3.7 and 3.8. This means there has been a lot of flux in how Python has sought to deal with typing through type annotations.

It also doesn't help that python is both duck-typed and nominally typed. That is, when accessing an attribute of an object, Python is duck-typed. The object will only be checked to see if it has an attribute at runtime, and only when immediately requested. However, Python also has nominal typing features. Nominal typing is where one type is declared to be a subclass of another. This can be through inheritance, or with the register() method of ABCMeta.

typing originally introduced its types using the idea of nominal typing. As of 3.8 it is trying to allow for the more pythonic structural typing. Structural typing is related to duck-typing, except that it is taken into consideration at "compile time" rather than runtime. For instance, when a linter is trying to detect possible type errors -- such as if you were to pass a dict to a function that only accepts sequences like tuples or list. With structural typing, a class B should be considered a subtype of A if it implements the all the methods of A, regardless of whether it has been declared to be a subtype of A (as in nominal typing).

Answer

sequences (little s) are a duck type. A sequence is any ordered collection of objects that provides random access to its members. Specifically, if it defines __len__ and __getitem__ and uses integer indices between 0 and n-1 then it is a sequence. A Sequence (big s) is a nominal type. That is, to be a Sequence, a class must be declared as such, either by inheriting from Sequence or being registered as a subclass.

A numpy array is a sequence, but it is not a Sequence as it is not registered as a subclass of Sequence. Nor should it be, as it does not implement the full interface promised by Sequence (things like count() and index() are missing).

It sounds like you want is a structured type for a sequence (small s). As of 3.8 this is possible by using protocols. Protocols define a set of methods which a class must implement to be considered a subclass of the protocol (a la structural typing).

from typing import Protocol
import numpy as np

class MySequence(Protocol):
    def __getitem__(self, index):
        raise NotImplementedError
    def __len__(self):
        raise NotImplementedError
    def __contains__(self, item):
        raise NotImplementedError
    def __iter__(self):
        raise NotImplementedError

def f(s: MySequence):
    for i in range(len(s)):
        print(s[i], end=' ')
    print('end')

f([1, 2, 3, 4]) # should be fine
arr: np.ndarray = np.arange(5)
f(arr) # also fine
f({}) # might be considered fine! Depends on your type checker

Protocols are fairly new, so not all IDEs/type checkers might support them yet. The IDE I use, PyCharm, does. It doesn't like f({}), but it is happy to consider a numpy array a Sequence (big S) though (perhaps not ideal). You can enable runtime checking of protocols by using the runtime_checkable decorator of typing. Be warned, all this does is individually check that each of the Protocols methods can be found on the given object/class. As a result, it can become quite expensive if your protocol has a lot of methods.

Answer from Dunes on Stack Overflow
🌐
Python
docs.python.org › 3 › builtins › stdtypes.html
Built-in Types — Python 3.14.7 documentation
If a container object’s __iter__() ... documentation for the yield expression. There are three basic sequence types: lists, tuples, and range objects....
🌐
Real Python
realpython.com › python-sequences
Python Sequences: A Comprehensive Guide – Real Python
March 18, 2026 - The term sequence doesn’t refer to a specific data type but to a category of data types that share common characteristics. ... A sequence is a data structure that contains items arranged in order, and you can access each item using an integer ...
Top answer
1 of 3
18

Brief introduction to typing in Python

Skip ahead if you know what structural typing, nominal typing and duck typing are.

I think much of the confusion arises from the fact that typing was a provisional module between versions 3.5 and 3.6. And was still subject to change between versions 3.7 and 3.8. This means there has been a lot of flux in how Python has sought to deal with typing through type annotations.

It also doesn't help that python is both duck-typed and nominally typed. That is, when accessing an attribute of an object, Python is duck-typed. The object will only be checked to see if it has an attribute at runtime, and only when immediately requested. However, Python also has nominal typing features. Nominal typing is where one type is declared to be a subclass of another. This can be through inheritance, or with the register() method of ABCMeta.

typing originally introduced its types using the idea of nominal typing. As of 3.8 it is trying to allow for the more pythonic structural typing. Structural typing is related to duck-typing, except that it is taken into consideration at "compile time" rather than runtime. For instance, when a linter is trying to detect possible type errors -- such as if you were to pass a dict to a function that only accepts sequences like tuples or list. With structural typing, a class B should be considered a subtype of A if it implements the all the methods of A, regardless of whether it has been declared to be a subtype of A (as in nominal typing).

Answer

sequences (little s) are a duck type. A sequence is any ordered collection of objects that provides random access to its members. Specifically, if it defines __len__ and __getitem__ and uses integer indices between 0 and n-1 then it is a sequence. A Sequence (big s) is a nominal type. That is, to be a Sequence, a class must be declared as such, either by inheriting from Sequence or being registered as a subclass.

A numpy array is a sequence, but it is not a Sequence as it is not registered as a subclass of Sequence. Nor should it be, as it does not implement the full interface promised by Sequence (things like count() and index() are missing).

It sounds like you want is a structured type for a sequence (small s). As of 3.8 this is possible by using protocols. Protocols define a set of methods which a class must implement to be considered a subclass of the protocol (a la structural typing).

from typing import Protocol
import numpy as np

class MySequence(Protocol):
    def __getitem__(self, index):
        raise NotImplementedError
    def __len__(self):
        raise NotImplementedError
    def __contains__(self, item):
        raise NotImplementedError
    def __iter__(self):
        raise NotImplementedError

def f(s: MySequence):
    for i in range(len(s)):
        print(s[i], end=' ')
    print('end')

f([1, 2, 3, 4]) # should be fine
arr: np.ndarray = np.arange(5)
f(arr) # also fine
f({}) # might be considered fine! Depends on your type checker

Protocols are fairly new, so not all IDEs/type checkers might support them yet. The IDE I use, PyCharm, does. It doesn't like f({}), but it is happy to consider a numpy array a Sequence (big S) though (perhaps not ideal). You can enable runtime checking of protocols by using the runtime_checkable decorator of typing. Be warned, all this does is individually check that each of the Protocols methods can be found on the given object/class. As a result, it can become quite expensive if your protocol has a lot of methods.

2 of 3
1

I think the most practical way to define a sequence in Python is 'A container that supports indexing with integers'.

The Wikipedia definition also holds:

a sequence is an enumerated collection of objects in which repetitions are allowed and order does matter.

To validate if an object is a sequence, I would emulate the logic from the Sequence Protocol:

hasattr(test_obj, "__getitem__") and not isinstance(test_obj, collections.abc.Mapping) 
🌐
GeeksforGeeks
geeksforgeeks.org › dsa › sequence-and-series-in-python
Sequence and Series in Python - GeeksforGeeks
July 23, 2025 - A Sequence is an ordered list of numbers following a specific pattern, while a series is the sum of the elements of a sequence. This tutorial will cover arithmetic sequences, geometric sequences, and how to work with them in Python.
🌐
YouTube
youtube.com › watch
What is a sequence in Python? - YouTube
Sequences are iterables that have a length. Sequences are ordered collections (they maintain the order of their contents). The most common sequences built-in...
Published: July 10, 2023
🌐
TutorialsPoint
tutorialspoint.com › article › python-sequence-types
Python Sequence Types
March 25, 2026 - In Python programming, sequence types are fundamental data structures that hold an ordered collection of items. The main sequence types include Lists, Strings, Tuples, and Range objects.
Find elsewhere
🌐
Medium
medium.com › @gauravverma.career › sequence-in-python-705f9904313f
Sequence in Python. Sequence is any ordered set in python… | by Gaurav Verma | Medium
December 7, 2025 - Sequence in Python Sequence is any ordered set in python like List, Tuple, String List: List is mutable and can store any type of object. Tuple: Tuple is immutable and can store any type of …
🌐
TutorialsPoint
tutorialspoint.com › article › what-is-a-sequence-data-type-in-python
What is a sequence data type in Python?
Sequence data types in Python are ordered collections that allow you to store and access multiple items using indexing. The three main sequence data types are lists, strings, and tuples.
🌐
Just Academy
justacademy.co › blog-detail › what-is-sequence-in-python
What is Sequence in Python by Roshan Chaturvedi | JustAcademy
In Python, a sequence is an ordered collection of items where each item is identified by an index. Sequences are useful for storing and manipulating multiple values together, allowing for easy access, modification, and iteration over the elements.
🌐
Python
docs.python.org › 3 › builtins › functions.html
Built-in Functions — Python 3.14.7 documentation
For integers, the result is the same as (a // b, a % b). For floating-point numbers the result is (q, a % b), where q is usually math.floor(a / b) but may be 1 less than that. In any case q * b + a % b is very close to a, if a % b is non-zero it has the same sign as b, and 0 <= abs(a % b) < abs(b). ... Return an enumerate object. iterable must be a sequence, an iterator, or some other object which supports iteration.
🌐
InformIT
informit.com › articles › article.aspx
Sequences in the Python Programming Language | Shared Operations | InformIT
Covers the import group of types known as sequences, an ordered, finite collection of items, in Python.
🌐
Python Morsels
pythonmorsels.com › make-a-sequence
How to make a sequence - Python Morsels
April 3, 2023 - Sign in to your Python Morsels account to save your screencast settings. Don't have an account yet? Sign up here. ... Sequences in Python are objects that can be looped over, can be indexed and have a length.
🌐
Scaler
scaler.com › home › topics › what are sequence data types in python?
What are Sequence Data Types in python? - Scaler Topics
May 4, 2023 - We have four built-in (general) data structures in python namely - lists, dictionaries, tuples and sets. Apart from these, we have some user-defined data structures in python like stacks, queues, trees, linked lists, graphs, and hashmaps. There are mainly six types of sequence data type in Python programming language, they are as follows:
🌐
Runestone Academy
runestone.academy › ns › books › published › fopp › Sequences › intro-Sequences.html
6.1. Introduction: Sequences — Foundations of Python Programming
Usually data is in the form of some kind of collection or sequence. For example, a grocery list helps us keep track of the individual food items we need to buy, and our todo list organizes the things we need to do each day. Notice that both the grocery list and the todo list are not even concerned with numbers as much as they are concerned with words. This is true of much of our daily life, and so Python provides us with many features to work with lists of all kinds of objects (numbers, words, etc.) as well as special kind of sequence, the character string, which you can think of as a sequence of individual letters.
🌐
Medium
pythonflood.com › python-sequences-weaving-the-story-of-order-and-logic-23dff398f83e
Python Sequences - Weaving the Story of Order and Logic. | by Rinu Gour | PythonFlood
July 11, 2023 - In Python, a sequence is a collection of objects, arranged in a particular order. A sequence can be either a list, a tuple, or a string…
🌐
Python
docs.python.org › 3 › library › itertools.html
itertools — Functions creating iterators for efficient looping
Added in version 3.1. ... Make an iterator that returns evenly spaced values beginning with start. Can be used with map() to generate consecutive data points or with zip() to add sequence numbers.
🌐
IDC Online
idc-online.com › technical_references › pdfs › information_technology › Sequences_in_Python.pdf pdf
Sequences in Python
Element selection. A sequence has an element corresponding to any non-negative · integer index less than its length, starting at 0 for the first element.
🌐
Facebook
facebook.com › pybeginner › posts › common-python-sequence-data-typespythonsequences-datatypes-learnpython › 1502851361882904
Common Python Sequence Data Types ...
Explore the things you love · Log into Facebook · English (US) · فارسی · العربية · Türkçe · Deutsch · Français (France) · Polski · More languages…