Dans un tl;dr mode:
C'est parce que les deux fonctions existent pour les deux affaires différentes, comme on peut le voir en unicode_strip
; do_strip
et _PyUnicodeXStrip
de la première exécution beaucoup plus rapide que la seconde.
La fonction do_strip
est pour le cas courant str.strip()
où aucun des arguments existent et do_argstrip
(qui s'enroule _PyUnicode_XStrip
) pour le cas où l' str.strip(arg)
est appelé, j'.e arguments sont fournis.
do_argstrip
vérifie juste le séparateur et si elle est valide et n'est pas égal à None
(auquel cas il appelle do_strip
) il appelle _PyUnicode_XStrip
.
Les deux do_strip
et _PyUnicode_XStrip
suivre la même logique, les deux compteurs sont utilisés, l'un égal à zéro et l'autre égal à la longueur de la chaîne.
À l'aide de deux while
boucles, le premier compteur est incrémenté jusqu'à ce qu'une valeur n'a d'égale que le séparateur est atteint et que le deuxième compteur est décrémenté jusqu'à ce que la même condition soit remplie.
La différence réside dans la façon de vérifier si le caractère actuel n'est pas égale à la séparation est effectuée.
Pour do_strip
:
Dans le cas le plus fréquent où les caractères de la chaîne à split peut être représenté en ascii
un petit boost de performance est présent.
while (i < len) {
Py_UCS1 ch = data[i];
if (!_Py_ascii_whitespace[ch])
break;
i++;
}
- Accéder à l'actualité des données est réalisé rapidement, en accédant au sous-jacents au tableau:
Py_UCS1 ch = data[i];
- Le vérifier si un caractère est un espace blanc est faite par un simple index de tableau dans un tableau appelé
_Py_ascii_whitespace[ch]
.
Donc, en bref, c'est assez efficace.
Si les personnages ne sont pas dans l' ascii
gamme, les différences ne sont pas aussi drastiques mais ils ne ralentissent l'exécution globale vers le bas:
while (i < len) {
Py_UCS4 ch = PyUnicode_READ(kind, data, i);
if (!Py_UNICODE_ISSPACE(ch))
break;
i++;
}
- L'accès se fait avec
Py_UCS4 ch = PyUnicode_READ(kind, data, i);
- Vérifier si le caractère est une espace est fait par l'
Py_UNICODE_ISSPACE(ch)
macro (qui appelle tout simplement une autre macro: Py_ISSPACE
)
Pour _PyUnicodeXStrip
:
Pour ce cas, l'accès aux données sous-jacentes sont, comme dans le cas précédent, avec l' PyUnicode_Read
; le chèque, sur l'autre main, pour voir si le caractère est un espace blanc (ou tout autre caractère que nous avons fourni) est raisonnablement un peu plus complexe.
while (i < len) {
Py_UCS4 ch = PyUnicode_READ(kind, data, i);
if (!BLOOM(sepmask, ch))
break;
if (PyUnicode_FindChar(sepobj, ch, 0, seplen, 1) < 0)
break;
i++;
}
PyUnicode_FindChar
est utilisé, ce qui, bien qu'efficace, est beaucoup plus complexe et plus lent par rapport à une matrice d'accès. Pour chaque caractère dans la chaîne, il est appelé pour voir si ce caractère est contenue dans le séparateur(s) que nous avons fournis. Comme la longueur de la chaîne augmente, l'overhead introduit par l'appel de cette fonction en permanence.
Pour ceux qui sont intéressés, PyUnicode_FindChar
après quelques vérifications, finira par appel d' find_char
à l'intérieur d' stringlib
qui, dans le cas où la longueur des séparateurs < 10
boucle jusqu'à ce qu'il trouve le personnage.
En dehors de cela, considérons les fonctions supplémentaires qui doivent déjà être appelé pour obtenir ici.
Comme pour lstrip
et rstrip
, la situation est similaire. Des drapeaux pour le mode d'entrelacement pour effectuer existent, à savoir: RIGHTSTRIP
pour rstrip
, LEFTSTRIP
pour lstrip
et BOTHSTRIP
pour strip
. La logique à l'intérieur d' do_strip
et _PyUnicode_XStrip
est effectuée de façon conditionnelle basée sur le pavillon.