Open In App

Python Generics

Last Updated : 15 Apr, 2024
Improve
Improve
Like Article
Like
Save
Share
Report

Python generics are type hints in Python. that allow you to write functions and classes that can work with any data type. In this article, we will discuss Python Generics with code examples.

What are Python Generics?

Python generics are like hints in Python. They came out in Python 3.5 and newer versions. They let you say what type of things your variables, functions, and results are. It helps you write down what kind of things your code is dealing with, but it doesn’t make the computer check it while running the code. This makes your code easier to read and work with, especially when you are working on big projects or with other people.

Python Generics Example

Below, are examples of Python Generics in Python.

Example 1: Python Generics with Function

In this example, the below code defines a generic function element that retrieves the first element from a list of any type. It employs Python’s TypeVar to denote the placeholder type T. The function is demonstrated with integer and string lists, printing their respective first elements.

Python3
from typing import TypeVar, List

T = TypeVar('T')

def element(items: List[T]) -> T:
    return items[0]

# Usage
print(element([1, 2, 3])) 
print(element(['a', 'b', 'c']))  

Output

1
a

Example 2: Python Generics with Different Data Types

In this example, below code define a generic function combine that concatenates two different data types T and U into a string. It offers flexibility for combining diverse data types while ensuring type safety. Examples showcase combining integers and strings, with concatenated strings

Python3
from typing import TypeVar

T = TypeVar('T')
U = TypeVar('U')

def combine(a: T, b: U) -> str:
    return str(a) + str(b)

# Usage
print(combine(10, 20)) 
print(combine('hello', 2020)) 

Output

1020
hello2020

Example 3: Python Generics with Class

In this example, code defines a generic class Container using TypeVar and Generic, allowing it to hold any type of content. Instances container_int and container_str are created, holding an integer and a string respectively, and their content is retrieved using the retrieve_content method.

Python3
from typing import TypeVar, Generic

T = TypeVar(Generic[T])

class Container:
    def __init__(self, content: T):
        self.content = content
    
    def retrieve_content(self) -> T:
        return self.content

# Usage
container_int = Container(10)
container_str = Container('GeeksforGeeks')

print(container_int.retrieve_content()) 
print(container_str.retrieve_content())  

Output

10
GeeksforGeeks

Python Generics with Duck Typing

Duck typing and Python generics are two different concepts, but they can be related in how they allow for flexible and dynamic programming in Python.

For know More about Duck Typing Click Here

Now, let’s see how these two concepts can be related with an example:

Python does not have the concept of generics before Python3.5, however you might argue that every function is generic because the parameters are not typed. This is a duck typing approach, which means that anything that walks and quacks like a duck is regarded as such. So, normally, “generic” functions would just verify if the parameters or objects had the bare minimum of required properties and then handle the data accordingly.

Example : In below code, Python generics enable type constraints for functions like process_data, ensuring that inputs conform to expected types; meanwhile, duck typing allows objects to be treated as the required type based on their behavior, irrespective of their explicit type, as demonstrated in process_data‘s dynamic handling of objects with a quack method.

Python3
from typing import TypeVar, Iterable

# Declare type variable
T = TypeVar('T')  

def process_data(data: Iterable[T]) -> None:
    for item in data:
        # Check if the object has a quack method, then call it
        if hasattr(item, 'quack') and callable(item.quack):
            item.quack()
        else:
            print(f"This object of type {type(item).__name__} doesn't quack like a duck!")

# Example class
class Duck:
    def quack(self):
        print("Quack!")

# Another class with similar behavior
class AnotherBird:
    def quack(self):
        print("Quack!")

# Using duck typing with process_data function
duck_obj = Duck()
another_bird_obj = AnotherBird()

# Both objects "quack" like a duck
duck_list = [duck_obj, another_bird_obj]  

# We can pass duck_list to process_data because both objects have a quack method
process_data(duck_list)  

Output

Quack!
Quack!


Like Article
Suggest improvement
Previous
Next
Share your thoughts in the comments

Similar Reads