Python generics
satya - 2/19/2024, 12:01:52 PM
Introductory article on python generics
Introductory article on python generics
satya - 2/19/2024, 12:18:45 PM
Generics in python: Kansas State University book
satya - 2/19/2024, 12:19:25 PM
it has
- quality: medium
- good introduction
- practical use
satya - 2/19/2024, 12:26:06 PM
Clear as mud: Python reference doc on it
satya - 2/19/2024, 1:02:42 PM
An example
#need for old generics < 3.5
from typing import List
def tesGenericLists():
oldlist: List[int] = [1,2,3] # This is an old generics
newlist: list[int] = [4,5,6] # new one is native
print(oldlist)
print(newlist)
satya - 2/19/2024, 1:03:32 PM
Key point
- Look at list[Blah]
- The "list" class in Python now is a generic class that takes "Blah" as its type input.
- It is generics out of the box
satya - 2/19/2024, 1:07:19 PM
Various syntaxes
#variable definitions
x: SomeGenericClass[Type]
#class inheritance
class SomeClass(SomeGenericClass[Type])
satya - 2/19/2024, 1:49:37 PM
An example with lists
"""
*************************************************
* Explain generics: lesson 2
*
* 1. You have to enable strick typing
* 2. MyList2(list[Person]): means I am extending person list
* 3. MyList(Generic[Person]): will not work
* 4. MyList(Generic[TypeVar("T", bound=Person)]) will work
* 5. See code below
*
*************************************************
"""
from baselib import baselog as log
from typing import TypeVar, Generic
class Person():
def __init__(self, name: str):
self.name = name
def __repr__(self) -> str:
return self.name
#
# You are saying my class works with "person" objects
# It is NOT saying I am a list of Persons
# Note: you have to enable strict typing to see the implications
#
T = TypeVar ("T", bound=Person)
class MyList(Generic[T]):
persons: list[T] = []
def addPerson(self, obj: T):
self.persons.append(obj)
# Extending a list of persons
class MyList2(list[Person]):
pass
"""
# won't work
class MyList3(Generic[Person]):
pass
"""
def testPList():
personList = MyList[Person]()
#This will not work below if strict typing is enabled
#personList.addPerson(1)
personList.addPerson(Person(name="satya"))
print(personList.persons)
def testPList2():
personList = MyList2()
#fails
#personList.append(1234)
personList.append(Person(name="satya"))
print(personList)
def localTest():
log.ph1("Starting local test")
testPList()
testPList2()
log.ph1("End local test")
if __name__ == '__main__':
localTest()
satya - 2/19/2024, 1:53:56 PM
Although works, doesn't seem like a good example!!
Although works, doesn't seem like a good example!!
satya - 2/19/2024, 2:48:01 PM
Example of a generic pair
from typing import Generic, TypeVar
# Define two type variables, T and U, which can be any types
T = TypeVar('T')
U = TypeVar('U')
# Define a generic class Pair, which can hold two items of types T and U
class Pair(Generic[T, U]):
def __init__(self, first: T, second: U):
self.first = first
self.second = second
def get_first(self) -> T:
return self.first
def get_second(self) -> U:
return self.second
def __repr__(self) -> str:
return f'Pair({self.first!r}, {self.second!r})'
# Example usage
if __name__ == "__main__":
# Pair of an integer and a string
pair_int_str = Pair(1, "Apple")
print(pair_int_str)
# Pair of a string and a list of floats
pair_str_list = Pair("Temperatures", [32.5, 31.8, 30.2])
print(pair_str_list)
# Accessing elements
print(pair_int_str.get_first()) # Output: 1
print(pair_int_str.get_second()) # Output: Apple
print(pair_str_list.get_second()) # Output: [32.5, 31.8, 30.2]
satya - 2/19/2024, 2:48:51 PM
Example of specific type of pairs
from typing import Generic, TypeVar
# Define base classes
class BaseT:
pass
class BaseU:
pass
# Define type variables with bounds
T = TypeVar('T', bound=BaseT)
U = TypeVar('U', bound=BaseU)
# Define a generic class Pair with type variables T and U
class Pair(Generic[T, U]):
def __init__(self, first: T, second: U):
self.first = first
self.second = second
def get_first(self) -> T:
return self.first
def get_second(self) -> U:
return self.second
def __repr__(self) -> str:
return f'Pair({self.first!r}, {self.second!r})'
# Example subclasses of BaseT and BaseU
class DerivedT(BaseT):
pass
class DerivedU(BaseU):
pass
# Usage with derived types
pair = Pair(DerivedT(), DerivedU())
print(pair)
satya - 2/19/2024, 4:15:31 PM
What I know so far
- The collection classes are already generic
- The sytax for making use of already defined generic classes
- Extending a genricised class with a specific type
- Defining a class that works with its own types
- Defining a class that works with only certain base type of classes
satya - 2/21/2024, 3:10:58 PM
Total list of Python Enhancement Proposals (PEP) for typing
satya - 2/21/2024, 3:35:45 PM
Standard library Documentation on TypeVar