52 votes

Devrais-je éviter de convertir en chaîne si une valeur est déjà une chaîne ?

Parfois, vous devez utiliser la compréhension de liste pour tout convertir en chaîne, y compris les chaînes elles-mêmes.

b = [str(a) for a in l]

Mais est-ce que je dois le faire :

b = [a if type(a)==str else str(a) for a in l]

Je me demandais si str sur une chaîne de caractères est suffisamment optimisé pour no créer une autre copie de la chaîne.

J'ai essayé :

>>> x="aaaaaa"
>>> str(x) is x
True

mais c'est peut-être parce que Python peut mettre les chaînes en cache et les réutiliser. Mais ce comportement est-il garanti pour toute valeur d'une chaîne ?

10 votes

Pour les objets de type chaîne, il s'agit de la chaîne elle-même. On dirait qu'il ne devrait pas y avoir de frais généraux.

2 votes

En Python 2, les deux extraits ne sont pas équivalents -. str(u"ó") soulève UnicodeEncodeError .

2 votes

Notez que la vérification du type en utilisant type(a)==str n'est pas du tout une bonne pratique. Vous devriez plutôt utiliser isinstance() à la place de la fonction intégrée.

66voto

Martijn Pieters Points 271458

Tester si un objet est déjà une chaîne est plus lent que de toujours convertir en chaîne.

C'est parce que le str() effectue également le même test (l'objet est-il déjà une chaîne de caractères). Vous a) faites le double du travail, et b) votre test est plus lent.

Remarque : pour Python 2, l'utilisation de str() en unicode comprend un encodage implicite en ASCII, ce qui peut échouer. Il se peut que vous ayez à traiter ces objets dans des cas particuliers. En Python 3, il n'est pas nécessaire de s'inquiéter de ce cas limite.

Comme il y a une certaine discussion autour de cela :

  • isinstance(s, str) a une signification différente lorsque s peut être un sous-classe de str . Comme les sous-classes sont traitées exactement comme n'importe quel autre type d'objet par str() (soit __str__ o __repr__ est appelé sur l'objet), cette différence importe ici.

  • Vous devez utiliser type(s) is str pour les contrôles de type exact. Les types sont des singletons, profitez-en, is est plus rapide :

    >>> import timeit
    >>> timeit.timeit("type(s) is str", "s = ''")
    0.10074466899823165
    >>> timeit.timeit("type(s) == str", "s = ''")
    0.1110201120027341
  • Utilisation de s if type(s) is str else str(s) est nettement plus lent pour le cas de non-chaîne :

    >>> import timeit
    >>> timeit.timeit("str(s)", "s = None")
    0.1823573520014179
    >>> timeit.timeit("s if type(s) is str else str(s)", "s = None")
    0.29589492800005246
    >>> timeit.timeit("str(s)", "s = ''")
    0.11716728399915155
    >>> timeit.timeit("s if type(s) is str else str(s)", "s = ''")
    0.12032335300318664

    (Les horaires de la s = '' sont très proches et ne cessent de s'échanger les places).

Tous les chronométrages de cet article ont été réalisés avec Python 3.6.0 sur un Macbook Pro 15" (mi 2015), OS X 10.12.3.

0 votes

Pouvez-vous s'il vous plaît donner un point de repère sur les cordes courtes et larges. En particulier en vérifiant le type à l'aide de isinstance() fonction.

0 votes

Concernant les cas limites (improbables) de Python 3 : stackoverflow.com/a/38982099/6260170

0 votes

@Chris_Rands : bien sûr, vous pouvez casser n'importe quelle méthode de dunder et donc tout ce qui appelle la méthode. __str__ y __repr__ Il n'y a pas d'exception :-) Le codage implicite pour unicode fait partie de l'implémentation par défaut et doit donc être signalé ; pour autant que je sache, la stdlib de Python 3 n'a pas de tels cas de figure.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X