While making a function to manipulate the TypeVar
from the typing module, I came across a problem.
My function do work but I wanted to make it faster so I used the timeit module to test some different versions.
However the result aren't what I expected.
Clearing some potential interrogation :
check_type(object , type)
is a function meant to test if an object correspond to a type (quite time consuming currently).
isTypeVar(type)
test if type is a TypeVar.
NullType
is a type that cannot describe an object so when it's tested with check_type
it always return False.
restrict_TypeVar_for_object(typeVar , object)
is the function that I have made in order to remove all of the constraints of my typeVar that doesn't correspond to object.
How I time my functions :
from timeit import timeit
func_version = """..."""
task="""..."""
timeit(task , setups=func_version , number=10_000_000)
Here is the task that I have timed (as you can see above I have repeated it 10 000 000 times) :
Number = int | float
T = TypeVar("T" , int , str , Number)
restrict_TypeVar_for_object(T , 5)
# --> TypeVar("T" , int , Number)
My test :
- 1st version :
def restrict_TypeVar_for_object(ty , obj):
if not isTypeVar(ty) : #Just to be sure that ty is a TypeVar
raise ValueError ('Expected a TypeVar as an argument')
if not ty.__constraints__ :
return type(obj)
lCons=[cons for cons in ty.__constraints__ if check_type(obj , cons)]
return (TypeVar(ty.__name__ , *lCons)
if len(lCons)>1 else
lCons[0]
if lCons else
NullType)
Takes : 378.5483768 s
- 2nd version :
def restrict_TypeVar_for_object(ty , obj):
if not isTypeVar(ty) : #Just to be sure that ty is a TypeVar
raise ValueError ('Expected a TypeVar as an argument')
if not ty.__constraints__ :
return type(obj)
return (TypeVar(ty.__name__ , *lCons)
if len(lCons:=[cons for cons in ty.__constraints__ if check_type(obj , cons)])>1 else
lCons[0]
if lCons else
NullType)
Takes : 376.9706139 s
- 3rd version :
def restrict_TypeVar_for_object(ty , obj):
if not isTypeVar(ty) : #Just to be sure that ty is a TypeVar
raise ValueError ('Expected a TypeVar as an argument')
if not ty.__constraints__ :
return type(obj)
return (TypeVar(ty.__name__ , *lCons[:-1])
if len(lCons:=[c for c in ty.__constraints__ if check_type(obj,c)]+[NullType]) > 2
else
lCons[0])
Takes : 391.5145658000001 s
As you can see the 2nd one is the quickest. However I wasn't expecting the 3rd one to be that slow compared to the other. To be frank I was even expecting it to be the quickest one because I did less if statement in this one.
I have 2 hypothesis for why this is the case :
-First, the walrus operator but if it is, why is the 2nd version the quickest.
-Second, the fact that I add [NullType]
at the end of lCons
but I don't know why it would be this time consuming.