hello, les pythonistes!
il y en a t’il un qui saurait me dire pourquoi une boucle for est environ 30% plus rapide q’un yield from?
je n’arrive pas à comprendre pourquoi
def _for():
start = time.time()
for i in range(8000):
for j in range(i):
yield j
print(time.time() - start)
def _yield():
start = time.time()
yield from (j for i in range(8000) for j in range(i))
print(time.time() - start)
>>> list(_for())
1.9730029106140137
>>>list(_yield())
2.552983045578003
Pas sur mais avec from dis import dis on peut voir les scope embriqués et un make et un appel de fonction supplémentaire - à priori les appels de fonction prennent du temps sous Python
_for est implémenté en une seule fonction, elle n’appelle que range
_yield est implémentée en deux fonctions : yield et l’expression génératrice (qui, sous le capot, est une fonction), et on fait l’aller retour d’une fonction à l’autre un bon nombre de fois (8000+7999+7998+… fois), ce qui a un coût.
Donc oui, c’est l’appel de fonction qui est coûteux (c’est toute une machinerie, l’appel d’une fonction), mais conclure “houla un appel de fonction coûte 30% du temps de calcul” n’est vrai que dans ce cas précis : c’est vrais ici parce que la fonction ne fais quasiment rien, donc le temps de l’appel commence à sacrément apparaître, mais pour une fonction qui fait “quelque chose”, le temps de l’appel serait négligable.
Pour la solution de @dancergraham, j’aurais tendance à mettre une espace après return, sinon ça ressemble à un appel de fonction, ce qui me gêne (dans le sens où ça peut gêner un débutant qui aurait encore du mal a faire la distinction “appel de fonction / sortie d’une fonction” (aller dans un sens ou dans l’autre dans la pile d’appels).