web-dev-qa-db-fra.com

Est-ce que Python optimise une variable qui n'est utilisée que comme valeur de retour?

Existe-t-il une différence ultime entre les deux extraits de code suivants? Le premier attribue une valeur à une variable dans une fonction, puis renvoie cette variable. La deuxième fonction renvoie simplement la valeur directement.

Est-ce que Python les transforme en un bytecode équivalent? L'un d'entre eux est-il plus rapide?

Cas 1:

def func():
    a = 42
    return a

Cas 2:

def func():
    return 42
106
Jayesh

Non, ce n'est pas le cas.

La compilation en code d'octet CPython est uniquement transmise via un petit optimiseur de judas conçu pour ne faire que des optimisations de base (voir test_peepholer.py dans la suite de tests pour plus d'informations sur ces optimisations. ).

Pour jeter un coup d'œil à ce qui va réellement se passer, utilisez dis * pour voir les instructions générées. Pour la première fonction, contenant l'affectation:

from dis import dis
dis(func)
  2           0 LOAD_CONST               1 (42)
              2 STORE_FAST               0 (a)

  3           4 LOAD_FAST                0 (a)
              6 RETURN_VALUE

Alors que, pour la deuxième fonction:

dis(func2)
  2           0 LOAD_CONST               1 (42)
              2 RETURN_VALUE

Deux autres instructions (rapides) sont utilisées dans la première: STORE_FAST et LOAD_FAST . Celles-ci permettent de stocker et de récupérer rapidement la valeur dans le tableau fastlocals du cadre d'exécution actuel. Ensuite, dans les deux cas, un RETURN_VALUE Est effectué. Ainsi, la seconde est toujours légèrement plus rapide en raison du nombre réduit de commandes nécessaires à l'exécution.

En général, sachez que le compilateur CPython est conservatif dans les optimisations qu'il effectue. Ce n'est pas et ne cherche pas à être aussi intelligent que les autres compilateurs (qui, en général, ont aussi beaucoup plus d'informations à utiliser). L'objectif principal de la conception, en plus d'être manifestement correct, consiste à a) rester simple et b) à être aussi Swift que possible dans la compilation, de sorte que vous ne remarquiez même pas qu'une phase de compilation existe.

En fin de compte, vous ne devriez pas vous préoccuper de petits problèmes comme celui-ci. Le gain de vitesse est minime, constant et réduit au minimum par la surcharge induite par le fait que Python est interprété.

* dis est un petit module Python qui désassemble votre code, vous pouvez l'utiliser pour voir le bytecode Python que le VM va exécuter.

Remarque: Comme indiqué également dans un commentaire de @Jorn Vernee, cela est spécifique à l'implémentation CPython de Python. D'autres implémentations peuvent faire des optimisations plus agressives si elles le souhaitent, mais pas CPython.

136

Les deux sont fondamentalement les mêmes sauf que dans le premier cas, l'objet 42 Est simplement attribué à une variable nommée a ou, en d'autres termes, à des noms (c'est-à-dire a) font référence à valeurs (ie 42). Techniquement, il ne fait aucune tâche, en ce sens qu'il ne copie aucune donnée.

Alors que returning, cette liaison nommée a est renvoyée dans le premier cas, tandis que l’objet 42 Est renvoyé dans le deuxième cas.

Pour plus de lecture, reportez-vous à ce superbe article de Ned Batchelder

3
kmario23