Je joue avec les listes de compréhension et je suis tombé sur ce petit extrait sur un autre site:
return ''.join([`num` for num in xrange(loop_count)])
J'ai passé quelques minutes à essayer de répliquer la fonction (en tapant) avant de réaliser que le bit `num`
Le cassait.
Que fait le fait d'inclure une déclaration dans ces caractères? D'après ce que je peux voir, c'est l'équivalent de str (num). Mais quand je l'ai chronométré:
return ''.join([str(num) for num in xrange(10000000)])
Cela prend 4,09s alors que:
return ''.join([`num` for num in xrange(10000000)])
prend 2,43 s.
Les deux donnent des résultats identiques mais l'un est beaucoup plus lent. Qu'est-ce qui se passe ici?
EDIT: Curieusement ... repr()
donne des résultats légèrement plus lents que `num`
. 2,99 s contre 2,43 s. Utilisation de Python 2.6 (pas encore essayé 3.0).
Les backticks sont un alias obsolète pour repr()
. Ne les utilisez plus, la syntaxe a été supprimée dans Python 3.0.
L'utilisation de backticks semble être plus rapide que l'utilisation de repr(num)
ou num.__repr__()
dans la version 2.x. Je suppose que c'est parce qu'une recherche de dictionnaire supplémentaire est requise dans l'espace de noms global (pour repr
), ou dans l'espace de noms de l'objet (pour __repr__
), Respectivement.
L'utilisation du module dis
prouve mon hypothèse:
def f1(a):
return repr(a)
def f2(a):
return a.__repr__()
def f3(a):
return `a`
Démontage des spectacles:
>>> import dis
>>> dis.dis(f1)
3 0 LOAD_GLOBAL 0 (repr)
3 LOAD_FAST 0 (a)
6 CALL_FUNCTION 1
9 RETURN_VALUE
>>> dis.dis(f2)
6 0 LOAD_FAST 0 (a)
3 LOAD_ATTR 0 (__repr__)
6 CALL_FUNCTION 0
9 RETURN_VALUE
>>> dis.dis(f3)
9 0 LOAD_FAST 0 (a)
3 UNARY_CONVERT
4 RETURN_VALUE
f1
Implique une recherche globale pour repr
, f2
Une recherche d'attribut pour __repr__
, Tandis que l'opérateur de backtick est implémenté dans un opcode séparé. Comme il n'y a pas de surcharge pour la recherche dans le dictionnaire (LOAD_GLOBAL
/LOAD_ATTR
) Ni pour les appels de fonction (CALL_FUNCTION
), Les raccourcis sont plus rapides.
Je suppose que les gens de Python ont décidé qu'avoir une opération distincte de bas niveau pour repr()
n'en valait pas la peine, et avoir à la fois repr()
et backticks viole le principe
"Il devrait y avoir un - et de préférence un seul - moyen évident de le faire"
donc la fonctionnalité a été supprimée dans Python 3.0.
Les guillemets inversés ne sont généralement pas utiles et ont disparu dans Python 3.
Pour ce que ça vaut, ceci:
''.join(map(repr, xrange(10000000)))
est légèrement plus rapide que la version backtick pour moi. Mais s'inquiéter à ce sujet est probablement une optimisation prématurée.
Je suppose que num
ne définit pas la méthode __str__()
, donc str()
doit faire une deuxième recherche de __repr__
.
Les backticks recherchent directement __repr__
. Si c'est vrai, l'utilisation de repr()
au lieu des backticks devrait vous donner les mêmes résultats.