web-dev-qa-db-fra.com

f-strings en Python 3.6

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é?

28
nivhanin

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 fprefixed-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 
  • Les optimisations pour CPython pourraient accélérer .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 casformat est préférable. 

32

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
23
Aaron

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.

9
Gringo Suave

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
1
RinSlow