Pourquoi les littéraux de chaîne bruts de Python ne peuvent-ils pas se terminer par une simple barre oblique inversée?

StackOverflow https://stackoverflow.com/questions/647769

Question

Techniquement, un nombre impair de barres obliques inverses, comme décrit dans les documents .

>>> r'\'
  File "<stdin>", line 1
    r'\'
       ^
SyntaxError: EOL while scanning string literal
>>> r'\\'
'\\\\'
>>> r'\\\'
  File "<stdin>", line 1
    r'\\\'
         ^
SyntaxError: EOL while scanning string literal

Il semble que l'analyseur pourrait simplement traiter les barres obliques inverses dans les chaînes brutes comme des caractères normaux (n'est-ce pas ce que sont les chaînes brutes?), mais il me manque probablement quelque chose d'évident. TIA!

Était-ce utile?

La solution

La raison est expliquée dans la partie de cette section que j'ai surlignée en gras:

  

Les guillemets peuvent être échappés avec un   barre oblique inversée, , mais la barre oblique inversée reste   dans la ficelle; Par exemple, r """ est un   littéral de chaîne valide composé de deux   caractères: une barre oblique inverse et un double   citation; r " \ " n'est pas une chaîne valide   littéral (même une chaîne brute ne peut pas se terminer   dans un nombre impair de barres obliques inverses).   Plus précisément, une chaîne brute ne peut pas se terminer   dans une seule barre oblique inversée (depuis le   barre oblique inverse échapperait à la suivante   caractère de citation). Notez également qu'un   barre oblique inverse suivie d'une nouvelle ligne   est interprété comme ces deux personnages   dans le cadre de la chaîne, pas comme une ligne   suite.

Ainsi, les chaînes brutes ne sont pas brutes à 100%, il reste encore un traitement rudimentaire de la barre oblique inverse.

Autres conseils

L’idée fausse à propos des chaînes brutes de Python est que la plupart des gens pensent que la barre oblique inverse (dans une chaîne brute) n’est qu’un caractère normal, comme tous les autres. Ce n'est pas. La clé à comprendre est la séquence de tutoriel de ce python:

  

Lorsqu'un préfixe r ou R est présent, un caractère suivant un   la barre oblique inverse est incluse dans la chaîne sans modification, et toutes   des barres obliques inverses sont laissées dans la chaîne

Ainsi, tout caractère après une barre oblique inverse fait partie de la chaîne brute. Une fois que l'analyseur écrit une chaîne brute (non unicode) et rencontre une barre oblique inverse, il sait qu'il y a 2 caractères (une barre oblique inverse et un caractère le suivant).

De cette façon:

  

r'abc \ d ' comprend a, b, c, \, d

     

r'abc \ 'd' comprend a, b, c, \, ', d      

r'abc \ '' comprend a, b, c, \, '

et:

  

r'abc \ ' comprend a, b, c, \,' mais il n'y a pas de citation finale maintenant.

Le dernier cas montre que, d’après la documentation, un analyseur syntaxique ne parvient pas à trouver une citation de clôture car le dernier itinéraire indiqué ci-dessus fait partie de la chaîne, c.-à-d. la barre oblique inverse ne peut pas être la dernière ici car elle "dévorera" le caractère de fermeture de la chaîne.

C'est comme ça! Je le vois comme un de ces petits défauts de python!

Je ne pense pas qu'il y ait une bonne raison à cela, mais ce n'est certainement pas une analyse syntaxique; il est très facile d'analyser les chaînes brutes avec \ comme dernier caractère.

Le problème est que, si vous autorisez \ à être le dernier caractère d'une chaîne brute, vous ne pourrez pas mettre " à l'intérieur d'une chaîne brute. Il semble que python a accepté avec " au lieu de laisser \ comme dernier caractère.

Toutefois, cela ne devrait poser aucun problème.

Si vous craignez de ne pas pouvoir écrire facilement les chemins des dossiers Windows tels que c: \ mypath \ , ne vous inquiétez pas, vous pouvez les représenter sous la forme r & C: \ mypath " , et si vous devez ajouter un nom de sous-répertoire, ne le faites pas avec la concaténation de chaînes, car ce n’est pas la bonne façon de le faire! utilisez os.path.join

>>> import os
>>> os.path.join(r"C:\mypath", "subfolder")
'C:\\mypath\\subfolder'

Une autre astuce consiste à utiliser chr (92) lorsqu’il se traduit par "\".

J'ai récemment dû nettoyer une chaîne de barres obliques inverses et voici ce qui a fonctionné:

CleanString = DirtyString.replace(chr(92),'')

Je réalise que cela ne résout pas le problème "pourquoi" mais le fil attire de nombreuses personnes à la recherche d'une solution à un problème immédiat.

Pour que vous puissiez terminer une chaîne brute par une barre oblique, je vous suggère d'utiliser cette astuce:

>>> print r"c:\test"'\\'
test\

Depuis \ " est autorisé à l'intérieur de la chaîne brute. Ensuite, il ne peut pas être utilisé pour identifier la fin du littéral de chaîne.

Pourquoi ne pas arrêter d'analyser le littéral chaîne lorsque vous rencontrez le premier "?"

Si tel était le cas, alors \ " ne serait pas autorisé à l'intérieur du littéral de chaîne. Mais ça l'est.

La raison pour laquelle r '\' est syntaxiquement incorrect est que, bien que l'expression de chaîne soit brute, les guillemets utilisés (simples ou doubles) doivent toujours être échappés, car ils marqueraient la fin du texte. citer autrement. Donc, si vous voulez exprimer un seul guillemet dans une chaîne entre guillemets, il n'y a pas d'autre moyen que d'utiliser \ '. Il en va de même pour les guillemets doubles.

Mais vous pouvez utiliser:

'\\'

Un autre utilisateur qui a depuis supprimé sa réponse (ne sachant pas s'il souhaitait être crédité) a suggéré aux concepteurs de langage Python de simplifier la conception de l'analyseur en utilisant les mêmes règles d'analyse et en développant les caractères échappés au format brut. comme une réflexion après coup (si le littéral a été marqué comme brut).

Je pensais que c'était une idée intéressante et je l'inclue en tant que wiki communautaire pour la postérité.

En venant de C, il est assez clair pour moi qu'un simple \ fonctionne comme un caractère d'échappement vous permettant de mettre des caractères spéciaux tels que des nouvelles lignes, des tabulations et des guillemets dans des chaînes.

Cela interdit en effet \ comme dernier caractère car il échappera à la " et faire étouffer l'analyseur. Mais comme nous l’avons souligné précédemment, c’est légal.

  

Malgré son rôle, même une chaîne brute ne peut se terminer par un seul   barre oblique inverse, car la barre oblique inverse échappe à la citation suivante   caractère - vous devez encore échapper au caractère de citation qui l'entoure   l'intégrer dans la chaîne. C’est-à-dire que r " ... \ " n'est pas une chaîne valide   littéral: une chaîne brute ne peut pas se terminer par un nombre impair de barres obliques inverses.
  Si vous devez terminer une chaîne brute avec une simple barre oblique inversée, vous pouvez utiliser   deux et couper la seconde.

quelques conseils:

1) Si vous devez manipuler une barre oblique inversée pour le chemin, le module standard python os.path est votre ami. par exemple:

  

os.path.normpath ('c: / dossier1 /')

2) si vous voulez construire des chaînes avec une barre oblique inverse MAIS sans barre oblique inverse à la fin de votre chaîne, la chaîne brute est votre ami (utilisez le préfixe 'r' avant votre chaîne littérale). par exemple:

r'\one \two \three'

3) si vous devez préfixer une chaîne dans une variable X avec une barre oblique inverse, vous pouvez le faire:

X='dummy'
bs=r'\ ' # don't forget the space after backslash or you will get EOL error
X2=bs[0]+X  # X2 now contains \dummy

4) si vous devez créer une chaîne avec une barre oblique inverse à la fin, combinez les astuces 2 et 3:

voice_name='upper'
lilypond_display=r'\DisplayLilyMusic \ ' # don't forget the space at the end
lilypond_statement=lilypond_display[:-1]+voice_name

maintenant lilypond_statement contient "\ DisplayLilyMusic \ upper"

vive le python! :)

n3on

J'ai rencontré ce problème et trouvé une solution partielle qui convient à certains cas. Bien que python ne puisse pas terminer une chaîne avec une seule barre oblique inverse, celle-ci peut être sérialisée et enregistrée dans un fichier texte avec une seule barre oblique inverse à la fin. Par conséquent, si vous avez besoin d’enregistrer un texte avec une simple barre oblique inverse sur votre ordinateur, il est possible:

x = 'a string\\' 
x
'a string\\' 

# Now save it in a text file and it will appear with a single backslash:

with open("my_file.txt", 'w') as h:
    h.write(x)

BTW ne fonctionne pas avec json si vous le dumpez en utilisant la bibliothèque json de python.

Enfin, je travaille avec Spyder et j'ai remarqué que si j'ouvre la variable dans l'éditeur de texte de Spider en double-cliquant sur son nom dans l'explorateur de variable, elle est présentée avec une simple barre oblique inverse et peut être copiée dans le presse-papiers de cette façon. (ce n'est pas très utile pour la plupart des besoins mais peut-être pour certains ..).

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top