J'aime beaucoup m'intéresser au style de code et il est intéressant de savoir si, dans tous les cas, il serait préférable d'utiliser le nouveau style.
J'utilise beaucoup la fonction .format()
dans mes projets Python 3.5 et je crains qu'elle ne soit déconseillée lors des prochaines versions de Python à cause de ce nouveau type de littéraux de chaîne.
>>> name = "Test"
>>> f"My app name is {name}."
'My app name is Test.'
La fonction de chaîne formatée vient-elle remplacer complètement l’ancienne format()
?
Je comprends que cela repose sur l'idée que:
Simple, c'est mieux que complexe.
Cependant, qu'en est-il des problèmes de performances, existe-t-il une différence entre eux? Ou c'est juste un simple coup d'oeil de la même fonctionnalité?
Je crains qu'il ne soit obsolète lors des prochaines versions de Python
Ne le soyez pas, str.format
n'apparaît pas (et n'a pas de raison) de partir de sitôt, le PEP qui a introduit f
prefixed-strings even indique dans son résumé :
Ce PEP ne propose pas de supprimer ou de déconseiller les mécanismes de formatage de chaîne existants.
Des chaînes formatées ont été introduites pour remédier à certains des inconvénients des autres méthodes de formatage des chaînes; ne pas jeter les anciennes méthodes et forcer Dieu sait combien de projets utiliser f-string s'ils veulent que leur code fonctionne pour Python 3.6+.
En ce qui concerne les performances de ces dernières, il semble que je soupçonne au départ qu'elles pourraient être plus lentes, mais les f-string semblent facilement surperformer leurs homologues .format
:
➜ cpython git:(master) ./python -m timeit -s "a = 'test'" "f'formatting a string {a}'"
500000 loops, best of 5: 628 nsec per loop
➜ cpython git:(master) ./python -m timeit "'formatting a string {a}'.format(a='test')"
100000 loops, best of 5: 2.03 usec per loop
Celles-ci ont été effectuées sur la branche master du référentiel CPython au moment de la rédaction de cet article; ils sont définitivement sujets à changement:
f-strings
, en tant que nouvelle fonctionnalité, pourrait avoir des optimisations possibles .format
(par exemple, appels de méthode Speedup 1.2x _) Mais vraiment, ne vous inquiétez pas trop de la vitesse, de ce qui est plus lisible pour vous et pour les autres.
Dans de nombreux cas, il s'agira de f-strings
, mais dans certains cas où format
est préférable.
Pour approfondir la réponse de Jim et répondre à vos préoccupations en matière de performances, j'ai utilisé le module dis
de python pour comparer les instructions bytecode de deux fonctions syntaxiquement différentes, mais fonctionnellement équivalentes.
import dis
def f1():
a = "test"
return f"{a}"
def f2():
return "{a}".format(a='test')
print(dis.dis(f1))
print(dis.dis(f2))
Le résultat est:
11 0 LOAD_CONST 1 ('test') 2 STORE_FAST 0 (a) 12 4 LOAD_FAST 0 (a) 6 FORMAT_VALUE 0 8 RETURN_VALUE Aucun 15 0 LOAD_CONST 1 ('{a}') 2 LOAD_ATTR 0 (format) 4 LOAD_CONST 2 ('test') 6 LOAD_CONST 3 (('a',)) 8 CALL_FUNCTION_KW 1 10 RETURN_VALUE Aucun
On peut voir que la chaîne f gère le formatage sans appel d'attribut ni de fonction, ce qui peut imposer une vérification de type et une surcharge de mémoire. Selon timeit
, il en résulte un gain de performances d'environ 3x (pour mes fonctions spécifiques)
>>> timeit.timeit ('f1 ()', 'de __main__ import f1', nombre = 100000) 0.012325852433775708 >>> timeit.timeit ('f2 ()', 'à partir de __main__ import f2' , nombre = 100000) 0.036395029920726074
Une chose qui n’a pas été mentionnée (ce qui rend impossible la dépréciation des anciennes techniques) est que l’interpolation s’applique uniquement aux littéraux de chaîne. Cela signifie que la chaîne est rendue une fois au moment de l'exécution. Le modèle ne peut plus être utilisé avec des variables mises à jour, par exemple:
str_template.format(args)
Un autre cas est i18n, où string.Template est utilisé. De nombreux cas d'utilisation seraient impossibles sans les techniques plus anciennes. Profitez de l’interpolation de chaîne, mais ne l’utilisez pas là où cela ne convient pas, c’est-à-dire des endroits où vous avez besoin d’un modèle réutilisable.
Si vous voulez continuer à supporter Python 3.5, vous pouvez utiliser fstring
pip install fstring
from fstring import fstring
x = 1
y = 2.0
plus_result = "3.0"
print fstring("{x}+{y}={plus_result}")
# Prints: 1+2.0=3.0