Was genau machen "u" - und "r" -String-Flags und was sind rohe String-Literale?

651

Als ich diese Frage stellte , stellte ich fest, dass ich nicht viel über rohe Saiten wusste. Für jemanden, der behauptet, ein Django-Trainer zu sein, ist das scheiße.

Ich weiß, was eine Codierung ist, und ich weiß, was u''allein funktioniert, da ich Unicode bekomme.

  • Aber was r''genau macht das? Welche Art von Zeichenfolge ergibt sich daraus?

  • Und vor allem, was zum Teufel macht ur''das?

  • Gibt es schließlich eine zuverlässige Möglichkeit, von einer Unicode-Zeichenfolge zu einer einfachen Rohzeichenfolge zurückzukehren?

  • Ah, und übrigens, wenn Ihr System und Ihr Texteditor-Zeichensatz auf UTF-8 eingestellt sind, macht das u''tatsächlich etwas?

e-satis
quelle

Antworten:

683

Es gibt nicht wirklich eine "rohe Saite "; Es gibt rohe String-Literale , die genau die String-Literale sind, die 'r'vor dem Eröffnungszitat mit einem gekennzeichnet sind .

Ein "rohes String-Literal" ist eine etwas andere Syntax für ein String-Literal, bei dem ein Backslash \als "nur ein Backslash" verstanden wird (außer wenn es direkt vor einem Anführungszeichen steht, das das Literal sonst beenden würde) - nein "Escape-Sequenzen" zur Darstellung von Zeilenumbrüchen, Tabulatoren, Backspaces, Formular-Feeds usw. In normalen String-Literalen muss jeder Backslash verdoppelt werden, um nicht als Beginn einer Escape-Sequenz verwendet zu werden.

Diese Syntaxvariante existiert hauptsächlich, weil die Syntax von Mustern mit regulären Ausdrücken stark mit Backslashes ist (aber nie am Ende, daher spielt die obige "Ausnahme" -Klausel keine Rolle) und sie sieht ein bisschen besser aus, wenn Sie vermeiden, jedes von ihnen zu verdoppeln - - das ist alles. Es hat auch an Popularität gewonnen, native Windows-Dateipfade auszudrücken (mit Backslashes anstelle von regulären Schrägstrichen wie auf anderen Plattformen), aber das wird sehr selten benötigt (da normale Schrägstriche auch unter Windows meistens gut funktionieren) und unvollständig (aufgrund der "Except" -Klausel über).

r'...'ein Byte - String ist (in Python 2 *), ur'...'auch produziert genau die gleichen Typen von Zeichenkette (so zum Beispiel ist eine Unicode - Zeichenfolge (auch hier in Python 2 *), und jede der anderen drei Arten von zitieren r'...', r'''...''', r"...", r"""..."""sind alle Byte-Strings und so weiter).

Nicht sicher , was Sie unter „going back “ - es gibt keine eigen zurück und Vorwärtsrichtung, weil es keinen roher String - Typen , es ist nur eine alternative Syntax ganz normale String - Objekte, Byte oder Unicode auszudrücken , wie sie auch sein mag.

Und ja, in Python 2. * unterscheidet u'...' sich natürlich immer von nur '...'- ersteres ist eine Unicode-Zeichenfolge, letzteres ist eine Byte-Zeichenfolge. In welcher Codierung das Literal ausgedrückt werden könnte, ist ein völlig orthogonales Problem.

Betrachten Sie beispielsweise (Python 2.6):

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

Das Unicode-Objekt benötigt natürlich mehr Speicherplatz (sehr kleiner Unterschied für eine sehr kurze Zeichenfolge natürlich ;-).

Alex Martelli
quelle
6
Das Verständnis von "r" impliziert keine Typ- oder Codierungsprobleme, es ist viel einfacher.
E-Satis
23
Beachten Sie, dass ru "C: \ foo \ unstable" fehlschlägt, da \ u eine Unicode-Escape-Sequenz im ru-Modus ist. Der r-Modus hat \ u nicht.
Curtis Yallop
26
Beachten Sie, dass uund rnicht kommutativ sind: ur'str'funktioniert, ru'str'nicht. (zumindest in ipython 2.7.2 auf win7)
RafiK
7
Habe gerade rStrings getestet und festgestellt, dass wenn \ es das letzte Zeichen ist, es nicht als Literal genommen wird, sondern dem schließenden Zitat entgeht, was dazu führt SyntaxError: EOL while scanning string literal. So \\ muss noch für die letzte Instanz verwendet werden , \ in beliebigen Zeichenfolge mit einem Backslash.
Enteleform
1
Python 3.x - sys.getsizeof('cioa') == sys.getsizeof(r'cioa') == sys.getsizeof(u'cioa')(Ubuntu 16.04 mit UTF8 lang). Ebenso type('cioa') == type(r'cioa') == type(u'cioa'). ABER die rohe String-Interpolation macht einen Unterschied, alsosys.getsizeof('\ncioa') == sys.getsizeof(u'\ncioa') != sys.getsizeof(r'\ncioa')
Darren Weber
177

In Python gibt es zwei Arten von Zeichenfolgen: den traditionellen strund den neueren unicodeTyp. Wenn Sie ein Zeichenfolgenliteral ohne das uvordere eingeben, erhalten Sie den alten strTyp, in dem 8-Bit-Zeichen gespeichert sind , und mit dem uvorderen erhalten Sie den neueren unicodeTyp, in dem jedes Unicode-Zeichen gespeichert werden kann.

Das rändert den Typ überhaupt nicht, es ändert nur, wie das String-Literal interpretiert wird. Ohne das rwerden Backslashes als Escape-Zeichen behandelt. Mit dem rwerden Backslashes als wörtlich behandelt. In beiden Fällen ist der Typ derselbe.

ur ist natürlich eine Unicode-Zeichenfolge, bei der Backslashes wörtliche Backslashes sind und nicht Teil von Escape-Codes sind.

Sie können versuchen, eine Unicode-Zeichenfolge mithilfe der str()Funktion in eine alte Zeichenfolge zu konvertieren. Wenn jedoch Unicode-Zeichen in der alten Zeichenfolge nicht dargestellt werden können, wird eine Ausnahme angezeigt. Sie können sie zuerst durch Fragezeichen ersetzen, wenn Sie dies wünschen, aber dies würde natürlich dazu führen, dass diese Zeichen nicht mehr lesbar sind. Es wird nicht empfohlen, den strTyp zu verwenden, wenn Sie Unicode-Zeichen korrekt verarbeiten möchten.

Mark Byers
quelle
Danke, angenommen. Wie gesagt, ich wusste, was Unicode ist, ich wusste nicht, was "r" bedeutet und was die Kombination von "u" und "r" sein würde. Ich weiß es besser, Prost.
E-Satis
6
Backslashes werden in Raw-String-Literalen nicht als Literal behandelt, weshalb r"\"ein Syntaxfehler vorliegt.
4
Gilt nur für Python 2.
PaulMcG
60

'raw string' bedeutet, dass es so gespeichert wird, wie es erscheint. Zum Beispiel '\'ist nur ein Backslash statt ein Escape .

Xiaolong
quelle
3
... es sei denn, es ist das letzte Zeichen der Zeichenfolge. In diesem Fall entgeht es dem abschließenden Anführungszeichen.
Jez
36

Ein "u" -Präfix gibt an, dass der Wert unicodeeher den Typ als hat str.

Rohe String-Literale mit dem Präfix "r" maskieren alle darin enthaltenen Escape-Sequenzen, ebenso len(r"\n")wie 2. Da sie Escape-Sequenzen maskieren, können Sie ein String-Literal nicht mit einem einzigen Backslash beenden: Dies ist keine gültige Escape-Sequenz (z r"\". B. ).

"Raw" ist nicht Teil des Typs, sondern nur eine Möglichkeit, den Wert darzustellen. Zum Beispiel "\\n"und r"\n"sind identische Werte, so wie 32, 0x20und 0b100000identisch sind.

Sie können Unicode-Raw-String-Literale verwenden:

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

Die Codierung der Quelldatei bestimmt nur, wie die Quelldatei interpretiert wird. Sie wirkt sich nicht auf Ausdrücke oder Typen aus. Es wird jedoch empfohlen , Code zu vermeiden, bei dem eine andere Codierung als ASCII die Bedeutung ändern würde:

Dateien, die ASCII (oder UTF-8 für Python 3.0) verwenden, sollten kein Codierungscookie enthalten. Latin-1 (oder UTF-8) sollte nur verwendet werden, wenn in einem Kommentar oder einer Dokumentzeichenfolge ein Autorenname angegeben werden muss, für den Latin-1 erforderlich ist. Andernfalls ist die Verwendung von \ x-, \ u- oder \ U-Escapezeichen die bevorzugte Methode, um Nicht-ASCII-Daten in Zeichenfolgenliterale aufzunehmen.


quelle
30

Lassen Sie es mich einfach erklären: In Python 2 können Sie Zeichenfolgen in zwei verschiedenen Typen speichern.

Das erste ist ASCII, das in Python vom Typ str ist und 1 Byte Speicher verwendet. (256 Zeichen, speichert hauptsächlich englische Alphabete und einfache Symbole)

Der zweite Typ ist UNICODE , ein Unicode- Typ in Python. Unicode speichert alle Arten von Sprachen.

Standardmäßig bevorzugt Python den Typ str. Wenn Sie jedoch einen String im Unicode- Typ speichern möchten, können Sie u wie u'text ' vor den Text setzen oder dies tun, indem Sie unicode (' text ') aufrufen.

So u ist nur ein kurzer Weg , eine Funktion Guss zu nennen str zu Unicode . Das ist es!

Nun, im r- Teil, setzen Sie es vor den Text, um dem Computer mitzuteilen, dass es sich bei dem Text um Rohtext handelt. Backslash sollte kein Escapezeichen sein. r '\ n' erstellt kein neues Zeilenzeichen. Es ist nur einfacher Text mit 2 Zeichen.

Wenn Sie str in Unicode konvertieren und dort auch Rohtext einfügen möchten , verwenden Sie ur, da ru einen Fehler auslöst.

JETZT der wichtige Teil:

Sie können keinen Backslash mit r speichern , dies ist die einzige Ausnahme. Dieser Code erzeugt also einen Fehler: r '\'

Um einen Backslash (nur einen) zu speichern, müssen Sie '\\' verwenden.

Wenn Sie mehr als 1 Zeichen speichern möchten , können Sie immer noch verwenden , r wie r ‚\\‘ wird 2 Schrägstriche erzeugen , wie Sie erwartet haben .

Ich weiß nicht, warum r nicht mit einem Backslash-Speicher funktioniert, aber der Grund wird noch von niemandem beschrieben. Ich hoffe, dass es ein Fehler ist.

off99555
quelle
9
Sie werden feststellen, dass dies nicht nur r'\'illegal ist, Sie können auch keine einzige '\'an den Schwanz einer Saite legen . Genau wie r'xxxxxx\'ist eine illegale Zeichenfolge.
Diverger
Was ist mit Python 3?
Krissh
1
@Krissh Alle Python 3-Zeichenfolgen werden von Unicode unterstützt. Sein Typ wird sein str. Lesen Sie mehr zum besseren Verständnis hier: medium.com/better-programming/…
off99555
4

Vielleicht ist das offensichtlich, vielleicht auch nicht, aber Sie können die Zeichenfolge '\' erstellen, indem Sie x = chr (92) aufrufen.

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
Bomba Ps
quelle
4
x is yin True3 als True ausgewertet?
Habeeb Perwad
5
@HabeebPerwad, das liegt am String-Interning . Sie sollten sich niemals auf die Tatsache verlassen, x is ydie Trueaufgrund von Praktika bewertet wird . Verwenden x == ySie stattdessen (wenn Sie nicht prüfen, ob x und y genau dasselbe Objekt sind, das an einer einzelnen Speicherposition gespeichert ist).
Lucubrator
4

Unicode-String-Literale

Unicode-Zeichenfolgenliterale (Zeichenfolgenliterale mit dem Präfix u) werden in Python 3 nicht mehr verwendet . Sie sind weiterhin gültig, jedoch nur aus Kompatibilitätsgründen mit Python 2.

Rohe String-Literale

Wenn Sie ein Zeichenfolgenliteral erstellen möchten, das nur aus leicht typisierbaren Zeichen wie englischen Buchstaben oder Zahlen besteht, können Sie diese einfach eingeben : 'hello world'. Wenn Sie jedoch auch einige exotischere Charaktere einbeziehen möchten, müssen Sie eine Problemumgehung verwenden. Eine der Problemumgehungen sind Escape-Sequenzen . Auf diese Weise können Sie beispielsweise eine neue Zeile in Ihrer Zeichenfolge darstellen, indem Sie Ihrem Zeichenfolgenliteral einfach zwei leicht typisierbare Zeichen hinzufügen \n. Wenn Sie also die 'hello\nworld'Zeichenfolge drucken , werden die Wörter in separaten Zeilen gedruckt. Das ist sehr praktisch!

Andererseits gibt es einige Situationen, in denen Sie ein Zeichenfolgenliteral erstellen möchten, das Escape-Sequenzen enthält, diese jedoch nicht von Python interpretiert werden sollen. Sie möchten, dass sie roh sind . Schau 'dir diese Beispiele an:

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

In solchen Situationen können Sie dem Zeichenfolgenliteral einfach das folgende rZeichen voranstellen : r'hello\nworld'Von Python werden keine Escape-Sequenzen interpretiert. Die Zeichenfolge wird genau so gedruckt, wie Sie sie erstellt haben.

Rohe String-Literale sind nicht vollständig "roh"?

Viele Leute erwarten, dass die rohen String-Literale in dem Sinne roh sind, dass "alles , was zwischen den Anführungszeichen steht, von Python ignoriert wird" . Das ist nicht wahr. Python erkennt immer noch alle Escape-Sequenzen, interpretiert sie einfach nicht, sondern lässt sie unverändert. Dies bedeutet, dass rohe Zeichenfolgenliterale noch gültige Zeichenfolgenliterale sein müssen .

Aus der lexikalischen Definition eines String-Literal:

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

Es ist klar, dass Zeichenfolgenliterale (roh oder nicht), die ein einfaches Anführungszeichen enthalten 'hello'world'oder mit einem Backslash enden, 'hello world\'nicht gültig sind.

Jeyekomon
quelle