Moet ik het converteren naar een string vermijden als een waarde al een string is?

Soms moet je lijstbegrip gebruiken om alles naar string te converteren, inclusief strings zelf.

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

Maar moet ik het volgende doen:

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

Ik vroeg me af of strop een string voldoende geoptimaliseerd is om nietnog een kopie van de string te maken.

Ik heb geprobeerd:

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

maar dat kan zijn omdat Python strings kan cachen en ze opnieuw kan gebruiken. Maar is dat gedrag gegarandeerd voor elke waarde van een string?


Antwoord 1, autoriteit 100%

Testen of een object al een string is, gaat langzamer dan gewoon altijd converteren naar een string.

Dat komt omdat de str()methode ook exact dezelfde test maakt (is het object al een string). Je doet a) dubbel zoveel werk, en b) je test start langzamer op.

Opmerking: voor Python 2 omvat het gebruik van str()op unicode-objecten een impliciete codering naar ASCII, en dit kan mislukken. Mogelijk moet u nog speciale gevallen van dergelijke objecten behandelen. In Python 3 hoef je je geen zorgen te maken over die edge-case.

Omdat hier enige discussie over bestaat:

  • isinstance(s, str)heeft een andere betekenis wanneer seen subklassevan strkan zijn. Aangezien subklassen precies als elk ander type object worden behandeld door str()(ofwel __str__of __repr__wordt aangeroepen op het object), is dit verschil is hier belangrijk.
  • U moet type(s) is strgebruiken voor exacte typecontroles. Types zijn eenlingen, profiteer hiervan, isis sneller:

    >>> import timeit
    >>> timeit.timeit("type(s) is str", "s = ''")
    0.10074466899823165
    >>> timeit.timeit("type(s) == str", "s = ''")
    0.1110201120027341
    
  • Het gebruik van s if type(s) is str else str(s)is aanzienlijk langzamer voor de niet-tekenreeks:

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

    (De tijden voor de s = ''gevallen zijn zeer dichtbij en blijven van plaats wisselen).

Alle timings in dit bericht zijn uitgevoerd op Python 3.6.0 op een Macbook Pro 15″ (medio 2015), OS X 10.12.3.

Other episodes