The runtime outcome is effectively identical. The difference is that Python 3.12 introduces a way to declare type parameters right in the class definition instead of requiring manual TypeVar declarations.
Answer from Pavlo Kvas on Stack OverflowThe runtime outcome is effectively identical. The difference is that Python 3.12 introduces a way to declare type parameters right in the class definition instead of requiring manual TypeVar declarations.
The examples you have,
3.12+
class MyClass[T]: pass3.11
import typing as t T = t.TypeVar('T') class MyClass2(t.Generic[T]): pass
are not quite the same. From the Python docs on typing.TypeVar:
The variance of type variables is inferred by type checkers when they are created through the type parameter syntax or when
infer_variance=Trueis passed.
Therefore, the equivalent runtime behaviour in Python 3.11 and below is expressed as
import typing_extensions as t
T = t.TypeVar('T', infer_variance=True)
class MyClass2(t.Generic[T]): pass
This won't show up in any string representation of the class.
Support for Python v3.13's New Generic Syntax
Let's talk about python 3.12's new Type Parameter Syntax.
Generics/templates in python? - Stack Overflow
Generics: Making Go more Pythonic?
No. Typing is not the same as generic. The point is not converting a typed language to one without type, but allowing functions to be generic, eg accepting and returning a set of type. E.g. a sort function than can sort arrays of str and arrays of int. You're not mixing types, you are just postponing the type selection. Type checking will still happen at compile time.
More on reddit.comVideos
def Point[T](x: T, y: T):
...this looks great but, would this look better?
def [T] Point(x: T, y: T):
...Imagine cluttering this new syntax
def Point[T, E, S, L, A](x: T, y: T):
...doesn't this look messy?
Imagine doing it this way
def [T, E, S, L, A] Point(x: T, y: T):
...The other answers are totally fine:
- One does not need a special syntax to support generics in Python
- Python uses duck typing as pointed out by André.
However, if you still want a typed variant, there is a built-in solution since Python 3.5.
A full list of available type annotations is available in the Python documentation.
Generic classes:
from typing import TypeVar, Generic, List
T = TypeVar('T')
class Stack(Generic[T]):
def __init__(self) -> None:
# Create an empty list with items of type T
self.items: List[T] = []
def push(self, item: T) -> None:
self.items.append(item)
def pop(self) -> T:
return self.items.pop()
def empty(self) -> bool:
return not self.items
# Construct an empty Stack[int] instance
stack = Stack[int]()
stack.push(2)
stack.pop()
stack.push('x') # Type error
Generic functions:
from typing import TypeVar, Sequence
T = TypeVar('T') # Declare type variable
def first(seq: Sequence[T]) -> T:
return seq[0]
def last(seq: Sequence[T]) -> T:
return seq[-1]
n = first([1, 2, 3]) # n has type int.
Static type checking:
You must use a static type checker such as mypy or Pyre (developed by Meta/FB) to analyze your source code.
Install mypy:
python3 -m pip install mypy
Analyze your source code, for example a certain file:
mypy foo.py
or directory:
mypy some_directory
mypy will detect and print type errors. A concrete output for the Stack example provided above:
foo.py:23: error: Argument 1 to "push" of "Stack" has incompatible type "str"; expected "int"
References: mypy documentation about generics and running mypy
Python uses duck typing, so it doesn't need special syntax to handle multiple types.
If you're from a C++ background, you'll remember that, as long as the operations used in the template function/class are defined on some type T (at the syntax level), you can use that type T in the template.
So, basically, it works the same way:
- define a contract for the type of items you want to insert in the binary tree.
- document this contract (i.e. in the class documentation)
- implement the binary tree using only operations specified in the contract
- enjoy
You'll note however, that unless you write explicit type checking (which is usually discouraged), you won't be able to enforce that a binary tree contains only elements of the chosen type.