web-dev-qa-db-fra.com

Pourquoi repr (int) est-il plus rapide que str (int)?

Je me demande pourquoi repr(int) est plus rapide que str(int). Avec l'extrait de code suivant:

ROUNDS = 10000

def concat_strings_str():
    return ''.join(map(str, range(ROUNDS)))

def concat_strings_repr():
    return ''.join(map(repr, range(ROUNDS)))

%timeit concat_strings_str()
%timeit concat_strings_repr()

J'obtiens ces timings (python 3.5.2, mais des résultats très similaires avec 2.7.12):

 1.9 ms ± 17.9 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
 1.38 ms ± 9.07 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

Si je suis sur la bonne voie, la même fonction long_to_decimal_string Est appelée sous le capot.

Ai-je eu quelque chose de mal ou quoi d'autre qui me manque?


update : Cela n'a probablement rien à voir avec les méthodes __repr__ ou __str__ de int mais avec les différences entre repr() et str(), car int.__str__ et int.__repr__ sont en fait relativement rapides:

def concat_strings_str():
    return ''.join([one.__str__() for one in range(ROUNDS)])

def concat_strings_repr():
    return ''.join([one.__repr__() for one in range(ROUNDS)])

%timeit concat_strings_str()
%timeit concat_strings_repr()

résulte en:

2.02 ms ± 24.3 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
2.05 ms ± 7.07 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
34
Christian Geier

Parce que l'utilisation de str(obj) doit d'abord passer par type.__call__ Puis str.__new__ (Créer une nouvelle chaîne) puis PyObject_Str (faire une chaîne avec l'objet) qui invoque int.__str__ et, enfin , utilise la fonction que vous avez liée.

repr(obj), qui correspond à builtin_repr, appelle directement PyObject_Repr (récupère l'objet repr) qui appelle alors int.__repr__ qui utilise la même fonction que int.__str__.

De plus, le chemin qu'ils empruntent call_function (la fonction qui gère CALL_FUNCTION Opcode généré pour les appels) est légèrement différent.

Depuis la branche principale sur GitHub (CPython 3.7):

Comme l'indique votre mise à jour, il ne s'agit pas de int.__repr__ Vs int.__str__, Ils sont la même fonction après tout; il s'agit de savoir comment repr et str les atteindre. str a juste besoin de travailler un peu plus fort.

Je viens de comparer les implémentations str et repr dans la branche 3.5. Voir ici .

Il semble y avoir plus de contrôles dans str: enter image description here

12
aristotll

Il existe plusieurs possibilités car les fonctions CPython responsables des retours str et repr sont légèrement différentes.

Mais je suppose que la raison principale est que str est un type (une classe) et le str.__new__ la méthode doit appeler __str__ tandis que repr peut aller directement à __repr__.

8
MSeifert