Pouvez-vous me dire pourquoi '?\\\?'=='?\\\\?'
donne True
? Cela me rend fou et je ne trouve pas de réponse raisonnable ...
>>> list('?\\\?')
['?', '\\', '\\', '?']
>>> list('?\\\\?')
['?', '\\', '\\', '?']
Pouvez-vous me dire pourquoi '?\\\?'=='?\\\\?'
donne True
? Cela me rend fou et je ne trouve pas de réponse raisonnable ...
>>> list('?\\\?')
['?', '\\', '\\', '?']
>>> list('?\\\\?')
['?', '\\', '\\', '?']
list()
même:>>> '?\\\?'
'?\\\\?'
Réponses:
Fondamentalement, parce que python est légèrement indulgent dans le traitement de la barre oblique inverse. Citant de https://docs.python.org/2.0/ref/strings.html :
Contrairement à la norme C, toutes les séquences d'échappement non reconnues restent inchangées dans la chaîne, c'est-à-dire que la barre oblique inverse est laissée dans la chaîne .
(Souligné dans l'original)
Par conséquent, en python, ce n'est pas que trois barres obliques inverses sont égales à quatre, c'est que lorsque vous suivez une barre oblique inverse avec un caractère comme ?
, les deux ensemble apparaissent comme deux caractères, car ce \?
n'est pas une séquence d'échappement reconnue.
'escape''d'
). Vous n'avez même pas besoin de vous souvenir des autres personnages!
Cela est dû au fait que la barre oblique inverse agit comme un caractère d'échappement pour le ou les caractères qui le suivent immédiatement, si la combinaison représente une séquence d'échappement valide. La douzaine de séquences d'échappement sont répertoriées ici . Ils incluent les plus évidents tels que le saut de ligne \n
, la tabulation horizontale \t
, le retour chariot \r
et les plus obscurs tels que les caractères Unicode nommés utilisant \N{...}
, par exemple, \N{WAVY DASH}
qui représentent le caractère Unicode \u3030
. Le point clé est cependant que si la séquence d'échappement n'est pas connue, la séquence de caractères est laissée telle quelle dans la chaîne.
Une partie du problème peut également être que la sortie de l'interpréteur Python vous induit en erreur. Cela est dû au fait que les contre-obliques sont échappées lors de l'affichage. Cependant, si vous imprimez ces chaînes, vous verrez les barres obliques inverses supplémentaires disparaître.
>>> '?\\\?'
'?\\\\?'
>>> print('?\\\?')
?\\?
>>> '?\\\?' == '?\\?' # I don't know why you think this is True???
False
>>> '?\\\?' == r'?\\?' # but if you use a raw string for '?\\?'
True
>>> '?\\\\?' == '?\\\?' # this is the same string... see below
True
Pour vos exemples spécifiques, dans le premier cas '?\\\?'
, le premier \
échappe la deuxième barre oblique inverse en laissant une seule barre oblique inverse, mais la troisième barre oblique inverse reste en tant que barre oblique inverse car ce \?
n'est pas une séquence d'échappement valide. Par conséquent, la chaîne résultante est ?\\?
.
Dans le second cas '?\\\\?'
, la première barre oblique inverse échappe à la seconde, et la troisième barre oblique inverse échappe à la quatrième qui donne la chaîne ?\\?
.
C'est pourquoi trois contre-obliques sont identiques à quatre:
>>> '?\\\?' == '?\\\\?'
True
Si vous souhaitez créer une chaîne avec 3 barres obliques inverses, vous pouvez échapper à chaque barre oblique inverse:
>>> '?\\\\\\?'
'?\\\\\\?'
>>> print('?\\\\\\?')
?\\\?
ou vous pourriez trouver les chaînes "brutes" plus compréhensibles:
>>> r'?\\\?'
'?\\\\\\?'
>>> print(r'?\\\?')
?\\\?
Cela active le traitement de la séquence d'échappement pour le littéral de chaîne. Voir Littéraux de chaîne pour plus de détails.
'?\\\?'=='?\\?'
donne False
, je l'ai mal tapé. Cela devrait être '?\\\?'=='?\\\\?'
comme l'indique la question, je l'ai corrigé.
Depuis la page d'analyse lexicale python sous les littéraux de chaîne à l' adresse : https://docs.python.org/2/reference/lexical_analysis.html
Il existe un tableau qui répertorie toutes les séquences d'échappement reconnues.
\\ est une séquence d'échappement qui est === \
\? n'est pas une séquence d'échappement et est === \?
donc '\\\\' est '\\' suivi de '\\' qui est '\\' (deux échappés \)
et '\\\' est '\\' suivi de '\' qui est aussi '\\' (un échappé \ et un brut \)
aussi, il convient de noter que python ne fait pas la distinction entre les guillemets simples et doubles entourant une chaîne littérale, contrairement à certains autres langages.
Donc 'String' et 'String' sont exactement la même chose en python, ils n'affectent pas l'interprétation des séquences d'échappement.
La réponse de mhawke le couvre à peu près, je veux juste le reformuler sous une forme plus concise et avec des exemples minimaux qui illustrent ce comportement.
Je suppose qu'une chose à ajouter est que le traitement d'échappement se déplace de gauche à droite, de sorte que \n
trouve d'abord la barre oblique inverse, puis cherche un caractère à échapper, puis le trouve n
et l'échappe; \\n
trouve la première barre oblique inverse, trouve la seconde et l'échappe, puis la trouve n
et la voit comme un littéral n; \?
trouve une barre oblique inverse et recherche un caractère à échapper, trouve ?
qui ne peut pas être échappé, et donc le traite \
comme une barre oblique inverse littérale.
Comme l'a noté mhawke, la clé ici est que l'interpréteur interactif échappe la barre oblique inverse lors de l'affichage d'une chaîne. J'imagine que la raison en est de garantir que les chaînes de texte copiées de l'interpréteur dans l'éditeur de code sont des chaînes python valides. Cependant, dans ce cas, cette tolérance pour la commodité est source de confusion.
>>> print('\?') # \? is not a valid escape code so backslash is left as-is
\?
>>> print('\\?') # \\ is a valid escape code, resulting in a single backslash
'\?'
>>> '\?' # same as first example except that interactive interpreter escapes the backslash
\\?
>>> '\\?' # same as second example, backslash is again escaped
\\?