web-dev-qa-db-fra.com

Que font exactement les indicateurs de chaîne "u" et "r" et que sont des littéraux de chaîne bruts?

En demandant cette question , j'ai réalisé que je ne savais pas grand chose sur les chaînes brutes. Pour quelqu'un qui prétend être un entraîneur Django, c'est nul.

Je sais ce qu'est un encodage, et je sais ce que u'' fait seul, puisque j'obtiens ce qu'est Unicode.

  • Mais que fait exactement r''? Quel type de chaîne en résulte-t-il?

  • Et surtout que diable fait ur''?

  • Enfin, existe-t-il un moyen fiable de revenir d'une chaîne Unicode à une simple chaîne brute?

  • Ah, et d'ailleurs, si votre système et votre jeu de caractères de l'éditeur de texte sont réglés sur UTF-8, u'' fait-il réellement quelque chose?

577
e-satis

Il n'y a pas vraiment de "chaîne de caractères brute "; il existe des littéraux de chaîne bruts , qui sont exactement les littéraux de chaîne marqués d'un 'r' avant le guillemet d'ouverture.

Un "littéral de chaîne brute" est une syntaxe légèrement différente pour un littéral de chaîne, dans lequel une barre oblique inversée, \, est considérée comme signifiant "juste une barre oblique inversée" (sauf si elle est placée juste avant un guillemet littéral) - pas de "séquences d'échappement" pour représenter les retours à la ligne, les onglets, les backspaces, les sauts de formulaire, etc. Dans les littéraux de chaîne normaux, chaque barre oblique inversée doit être doublée pour éviter d'être considérée comme le début d'une séquence d'échappement.

Cette variante de syntaxe existe principalement parce que la syntaxe des modèles d'expression régulière est lourde avec des barres obliques inverses (mais jamais à la fin, de sorte que la clause "except" ci-dessus n'a pas d'importance) et cela semble un peu mieux lorsque vous évitez de doubler chacune d'elles - - c'est tout. Il a également acquis une certaine popularité pour l’expression des chemins de fichiers Windows natifs (avec des barres obliques inverses au lieu de barres obliques classiques, comme sur d’autres plates-formes), mais cela est très rarement nécessaire (car les barres obliques normales fonctionnent généralement très bien sous Windows) et imparfait (en raison de la clause "except" au dessus de).

r'...' est une chaîne d'octets (dans Python 2. *), ur'...' est une chaîne Unicode (encore une fois, dans Python 2. *), et des trois autres types de guillemets produit également exactement les mêmes types de chaînes (par exemple, r'...', r'''...''', r"...", r"""...""" sont toutes des chaînes d'octets, etc. ).

Vous ne savez pas ce que vous entendez par "aller en arrière " - il n'y a pas de sens intrinsèque en arrière et en avant, car il n'y a pas de chaîne brute type =, il s’agit simplement d’une syntaxe alternative pour exprimer des objets chaîne, octets ou unicode parfaitement normaux.

Et oui, dans Python 2. *, u'...'est bien sûr toujours distinct de juste '...' - le premier est une chaîne unicode, le second est une chaîne d'octets. Ce qui pourrait être exprimé en codant le littéral est un problème complètement orthogonal.

Par exemple, considérons (Python 2.6):

>>> sys.getsizeof('ciao')
28
>>> sys.getsizeof(u'ciao')
34

L’objet Unicode nécessite bien sûr plus d’espace mémoire (très petite différence pour une chaîne très courte, évidemment ;-).

625
Alex Martelli

Il existe deux types de chaînes en python: le type str traditionnel et le type unicode plus récent. Si vous tapez un littéral de chaîne sans le u, vous obtenez l'ancien type str qui stocke les caractères 8 bits, et avec le u devant, vous obtenez le nouveau type unicode qui peut stocker n'importe quel caractère Unicode.

r ne change pas le type du tout, il change simplement la façon dont le littéral de chaîne est interprété. Sans r, les barres obliques inverses sont traitées comme des caractères d'échappement. Avec r, les barres obliques inverses sont traitées comme des lettres. De toute façon, le type est le même.

ur est bien sûr une chaîne Unicode où les barres obliques inverses sont des barres obliques inverses littérales, et ne font pas partie des codes d'échappement.

Vous pouvez essayer de convertir une chaîne Unicode en une ancienne chaîne à l'aide de la fonction str(), mais s'il existe des caractères Unicode qui ne peuvent pas être représentés dans l'ancienne chaîne, vous obtiendrez une exception. Vous pouvez d'abord les remplacer par des points d'interrogation si vous le souhaitez, mais bien entendu, ces caractères seraient illisibles. Il n'est pas recommandé d'utiliser le type str si vous souhaitez gérer correctement les caractères unicode.

162
Mark Byers

'chaîne brute' signifie qu'il est stocké tel qu'il apparaît. Par exemple, '\' n'est qu'un barre oblique inverse au lieu d'un échappement.

53
xiaolong

Un préfixe "u" indique que la valeur a le type unicode plutôt que str.

Les littéraux de chaîne bruts, avec un préfixe "r", échappent à leurs séquences d'échappement. len(r"\n") vaut 2. Comme ils échappent, ils ne peuvent pas terminer un littéral de chaîne: il ne s'agit pas d'une séquence d'échappement valide. (par exemple, r"\").

"Raw" ne fait pas partie du type, c'est simplement une façon de représenter la valeur. Par exemple, "\\n" et r"\n" sont des valeurs identiques, tout comme 32, 0x20 et 0b100000 sont identiques.

Vous pouvez avoir des littéraux de chaîne bruts unicode:

>>> u = ur"\n"
>>> print type(u), len(u)
<type 'unicode'> 2

Le codage du fichier source détermine simplement comment interpréter le fichier source, il n’affecte pas les expressions ou les types. Cependant, il est recommandé d'éviter le code dans lequel un codage autre que ASCII changerait la signification:

Les fichiers utilisant ASCII (ou UTF-8, pour Python 3.0) ne doivent pas comporter de cookie de codage. Latin-1 (ou UTF-8) ne doit être utilisé que lorsqu'un commentaire ou une chaîne de documentation doit mentionner un nom d'auteur qui requiert Latin-1; sinon, utiliser\x,\u ou\U échappées est le moyen préféré pour inclure des données non-ASCII dans les littéraux de chaîne.

33
Roger Pate

Permettez-moi de l'expliquer simplement: Dans python 2, vous pouvez stocker une chaîne dans 2 types différents.

Le premier est ASCII qui est str tapez en python, il utilise 1 octet de mémoire. (256 caractères, stockera principalement des alphabets anglais et des symboles simples)

Le second type est UNICODE qui est nicode tapez en python, il utilise 2 octets de mémoire. (65 536 caractères, ce qui inclut tous les caractères de toutes les langues de la Terre)

Par défaut, python préférera str tapez mais si vous voulez stocker une chaîne dans nicode type, vous pouvez mettre dans devant le texte comme 'text ' ou vous pouvez le faire en appelant nicode (' text ')

Donc n'est qu'un moyen rapide d'appeler une fonction pour transtyper str vers nicode. C'est ça!

Maintenant, la partie r, vous la placez devant le texte pour indiquer à l'ordinateur que le texte est du texte brut. La barre oblique inversée ne doit pas être un caractère d'échappement. r '\ n' ne créera pas de nouveau caractère de ligne. C'est juste du texte brut contenant 2 caractères.

Si vous voulez convertir str en nicode et y mettre également du texte brut, utilisez r car r soulèvera une erreur.

MAINTENANT, la partie importante:

Vous ne pouvez pas stocker une barre oblique inverse en utilisant r, c'est la seule exception. Donc, ce code produira une erreur: r '\'

Pour stocker une barre oblique inverse (une seule), vous devez utiliser '\\'

Si vous souhaitez stocker plus de 1 caractères, vous pouvez toujours utiliser r comme r '\\' produira 2 barres obliques inverses comme prévu.

Je ne connais pas la raison pour laquelle r ne fonctionne pas avec un stockage à barre oblique inversée, mais la raison n'est encore décrite par personne. J'espère que c'est un bug.

27
off99555

Peut-être que c'est évident, peut-être que non, mais vous pouvez créer la chaîne '\' en appelant x = chr (92)

x=chr(92)
print type(x), len(x) # <type 'str'> 1
y='\\'
print type(y), len(y) # <type 'str'> 1
x==y   # True
x is y # False
4
Bomba Ps

Littéraux de chaîne Unicode

Les littéraux de chaîne Unicode (les littéraux de chaîne précédés de u) sont ne sont plus utilisés dans Python 3. Ils sont toujours valides mais niquement à des fins de compatibilité = avec Python 2.

Littéraux de chaîne bruts

Si vous souhaitez créer un littéral de chaîne composé uniquement de caractères faciles à saisir, tels que des lettres anglaises ou des chiffres, vous pouvez simplement les saisir: 'hello world'. Mais si vous souhaitez également inclure des caractères plus exotiques, vous devrez utiliser une solution de contournement. L'une des solutions de contournement est séquences d'échappement . De cette façon, vous pouvez par exemple représenter une nouvelle ligne dans votre chaîne en ajoutant simplement deux caractères faciles à saisir \n à votre littéral de chaîne. Ainsi, lorsque vous imprimez la chaîne 'hello\nworld', les mots sont imprimés sur des lignes séparées. C'est très pratique!

D'autre part, dans certaines situations, vous souhaitez créer un littéral de chaîne contenant des séquences d'échappement, mais vous ne souhaitez pas qu'elles soient interprétées par Python. Vous voulez qu'ils soient bruts . Regardez ces exemples:

'New updates are ready in c:\windows\updates\new'
'In this lesson we will learn what the \n escape sequence does.'

Dans de telles situations, vous pouvez simplement préfixer le littéral chaîne avec le caractère r comme ceci: r'hello\nworld' et aucune séquence d'échappement ne sera interprétée par Python. La chaîne sera imprimée exactement telle que vous l'avez créée.

Les littéraux de chaîne bruts ne sont pas complètement "bruts"?

Beaucoup de gens s'attendent à ce que les littéraux de chaîne bruts soient bruts, dans le sens où "tout élément placé entre les guillemets est ignoré par Python" . Ce n'est pas vrai. Python reconnaît toujours toutes les séquences d'échappement, il ne les interprète pas, il les laisse inchangées. Cela signifie que les littéraux de chaîne bruts doivent toujours être des littéraux de chaîne valides .

À partir du définition lexicale d'un littéral de chaîne:

string     ::=  "'" stringitem* "'"
stringitem ::=  stringchar | escapeseq
stringchar ::=  <any source character except "\" or newline or the quote>
escapeseq  ::=  "\" <any source character>

Il est clair que les littéraux de chaîne (bruts ou non) contenant un caractère guillemet simple: 'hello'world' ou se terminant par une barre oblique inversée: 'hello world\' ne sont pas valides.

1
Jeyekomon