「u」と「r」の文字列フラグは正確には何をしているのですか、また生の文字列リテラルとは何ですか?


652

尋ねながら、この質問を、私は生の文字列についてあまり知りませんでした実現しました。Djangoトレーナーであると主張する人にとっては、これはひどいことです。

エンコーディングとは何かを知ってu''います。Unicodeを取得しているので、それだけで何ができるのかはわかっています。

  • しかし、r''正確には何をしますか?その結果、どのような文字列になりますか?

  • そして何より、一体何をするのur''でしょうか?

  • 最後に、Unicode文字列から単純な生の文字列に戻る信頼できる方法はありますか?

  • ああ、ところで、システムとテキストエディタの文字セットがUTF-8に設定されている場合、u''実際には何をしますか?

回答:


683

「生の文字列」は実際にはありません。生の文字列リテラルがあります。これは、'r'、開始引用符の前にでです。

「生の文字列リテラル」は、文字列リテラルとは少し異なる構文です。 \は「単なるバックスラッシュ」を意味するものと見なされます(リテラルを終了させる引用符の直前にある場合を除く)-いいえ改行、タブ、バックスペース、フォームフィードなどを表す「エスケープシーケンス」。通常の文字列リテラルでは、エスケープシーケンスの開始と見なされないように、各バックスラッシュを2倍にする必要があります。

この構文バリアントは主に、正規表現パターンの構文がバックスラッシュで重いためです(ただし最後には決してないので、上記の "except"句は重要ではありません)。それぞれを2重にしないようにすると少し見栄えがよくなります- - それで全部です。(他のプラットフォームのように通常のスラッシュの代わりにバックスラッシュを使用して)ネイティブのWindowsファイルパスを表現することも人気を博しましたが、それが必要になることはほとんどなく(通常のスラッシュはWindowsでもほとんど正常に機能するため)、不完全です( "except"句により)上記)。

r'...'(パイソン2 *中)バイト文字列であり、ur'...'Unicode文字列(再び、Pythonで2 *)であり、そして引用他の3種類のいずれかが、文字列の正確に同じタイプの生成は、(そう例えばr'...'r'''...'''r"..."r"""..."""すべてがバイト文字列です)。

戻る」という意味がわからない-生の文字列型がないため、本質的に戻る方向と進む方向はなく、完全に通常の文字列オブジェクト、バイトまたはユニコードを表現するための代替構文にすぎません。

そして、はい、Pythonの2 *で、u'...' あるだけでは区別もちろんいつもの'...'-前者はUnicode文字列で、後者はバイト文字列です。リテラルのエンコードがどのように表現されるかは、完全に直交する問題です。

たとえば、(Python 2.6)を検討してください。

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

もちろん、Unicodeオブジェクトはより多くのメモリ空間を必要とします(非常に短い文字列では非常に小さな違いですが、明らかに;-)。


6
「r」を理解することは、タイプやエンコードの問題を意味するものではなく、はるかに簡単です。
e-satis 2010年

23
\ uはruモードのUnicodeエスケープシーケンスであるため、ru "C:\ foo \ unstable"は失敗することに注意してください。rモードには\ uはありません。
Curtis Yallop 14年

26
可換urはないことに注意してください:ur'str'機能しますが、機能しませんru'str'。(少なくともwin7上のipython 2.7.2で)
RafiK '10

7
ただ、テストされrた文字列をして気づいたならば\ 、それはリテラルとして運ばれたが、その代わり引き起こし、終了引用符をエスケープすることはありません最後の文字ですSyntaxError: EOL while scanning string literal。したがって、バックスラッシュで終わるすべての文字列の\\ 最後のインスタンスに使用する必要が\ あります。
Enteleform 2017年

1
python 3.x- sys.getsizeof('cioa') == sys.getsizeof(r'cioa') == sys.getsizeof(u'cioa')(Ubuntu 16.04とUTF8言語)。同様に、type('cioa') == type(r'cioa') == type(u'cioa')。しかし、生の文字列補間ので、違いを作るsys.getsizeof('\ncioa') == sys.getsizeof(u'\ncioa') != sys.getsizeof(r'\ncioa')
ダレン・ウェーバー

177

Pythonの文字列には、従来のstrタイプと新しいunicodeタイプの2つのタイプがあります。u前に文字列リテラルを入力すると、str8ビット文字を格納する古いタイプuが取得され、前に入力すると、unicode任意のUnicode文字を格納できる新しいタイプが取得されます。

rそれだけで、文字列リテラルの解釈方法を変更し、すべての種類を変更しません。がない場合r、円記号はエスケープ文字として扱われます。を使用するとr、バックスラッシュはリテラルとして扱われます。どちらにしても、タイプは同じです。

ur もちろんバックスラッシュはリテラルのバックスラッシュであり、エスケープコードの一部ではないUnicode文字列です。

str()関数を使用してUnicode文字列を古い文字列に変換することができますが、古い文字列で表現できないUnicode文字がある場合は、例外が発生します。必要に応じて、最初にそれらを疑問符に置き換えることもできますが、もちろん、これによりこれらの文字が読めなくなります。strUnicode文字を正しく処理したい場合は、タイプの使用はお勧めしません。


ありがとう、受け入れました。私が言ったように、私はユニコードが何であるかを知っていました、私は「r」が何を意味するのか、そして「u」と「r」の組み合わせが何であるかを知りませんでした。知ってますよ、乾杯。
e-satis

6
バックスラッシュは、未加工の文字列リテラルではリテラルとして扱われませんr"\"。そのため、構文エラーが発生します。

4
Python 2にのみ適用されます
PaulMcG 2018年

60

「生の文字列」とは、表示されるとおりに保存されることを意味します。例えば、'\'ちょうどであるバックスラッシュの代わりにエスケープ


3
...それが文字列の最後の文字である場合を除いて、その場合は終了引用符をエスケープします。
jez

36

「u」プレフィックスは、値がではunicodeなくタイプを持っていることを示しますstr

プレフィックスが「r」の生の文字列リテラルは、その中のエスケープシーケンスをエスケープし、len(r"\n")2をエスケープします。エスケープシーケンスをエスケープするため、文字列リテラルを単一のバックスラッシュで終了することはできませんr"\"。有効なエスケープシーケンスではありません(例:)。

「生」はタイプの一部ではなく、値を表す1つの方法にすぎません。たとえば、"\\n"r"\n"同じように、同じ値であり320x200b100000同じです。

あなたはユニコードの生の文字列リテラルを持つことができます:

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

ソースファイルのエンコードは、ソースファイルの解釈方法を決定するだけであり、それ以外の式や型には影響しません。ただし、ASCII以外のエンコーディングで意味が変わるコードは避けることをお勧めします。

ASCII(またはPython 3.0の場合はUTF-8)を使用するファイルには、コーディングCookieを含めないでください。Latin-1(またはUTF-8)は、コメントまたはドキュメント文字列がLatin-1を必要とする著者名を言及する必要がある場合にのみ使用する必要があります。それ以外の場合、文字列リテラルに非ASCIIデータを含めるには、\ x、\ u、または\ Uエスケープを使用することをお勧めします。


30

簡単に説明しましょう。Python2では、文字列を2つの異なるタイプで格納できます。

最初のものはASCIIです。、Pythonのstrタイプの、1バイトのメモリを使用します。(256文字、主に英語のアルファベットと単純な記号を格納します)

2番目のタイプはUNICODEです。ユニコードのpythonを入力します。Unicodeはすべてのタイプの言語を格納します。

デフォルトでは、Pythonはstrタイプを優先しますが、Unicodeタイプで文字列を保存する場合は、u'text 'のようにテキストの前にuを付けることができます。か、unicode(' text ')を呼び出してこれを行うことができます。

したがって、ustrunicodeにキャストする関数を呼び出すための短い方法です。それでおしまい!

次に、rの部分をテキストの前に置いて、テキストが生のテキストであることをコンピュータに伝えます。バックスラッシュはエスケープ文字であってはなりません。r '\ n'は改行文字を作成しません。これは、2文字を含むプレーンテキストです。

変換したい場合はSTRをするユニコードともそこに生のテキストを入れて、利用ウルのでruが、エラーが発生します。

今、重要な部分:

rを使用してバックスラッシュを1つ格納することはできません。これは唯一の例外です。したがって、このコードはエラーを生成します:r '\'

バックスラッシュ(1つのみ)を格納するには、「\\」を使用する必要があります

あなたは以上の1つの文字を格納したい場合は、まだ使用することができ、Rのようなr「を\\」あなたが期待通りに2つのバックスラッシュを生成します。

rが1つのバックスラッシュストレージで機能しない理由はわかりませんが、その理由はまだ誰にも説明されていません。バグだといいですね。


9
r'\'違法であるだけ'\'でなく、文字列の末尾にシングルを置くことさえできないことに気付くでしょう。ちょうどr'xxxxxx\'違法な文字列です。
ダイバー:

Python 3はどうですか?
Krissh、

1
@Krisshすべてのpython 3文字列はUnicodeをサポートしています。タイプはになりますstr。詳細については、こちらをご覧ください。medium.com
programming

4

多分これは明らかかもしれませんが、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
x is ypython3でTrueと評価されますか?
Habeeb Perwad 2017年

5
@HabeebPerwad、それは文字列のインターンのためです。インターンのためにx is yたまたま評価されるという事実に決して頼るべきではありませんTrue。代わりに使用しますx == y(xとyが単一のメモリ位置に格納されているオブジェクトとまったく同じかどうかを確認しない場合)。
Lucubrator、2017

4

Unicode文字列リテラル

Unicode文字列リテラル(接頭辞がの文字列リテラルu)は、Python 3では使用さなくなりました。これらは引き続き有効ですが、互換性のためだけに使用さます。、Python 2とので。

生の文字列リテラル

英語の文字や数字など、簡単に入力できる文字だけで構成される文字列リテラルを作成する場合は、単純に入力できます'hello world'。しかし、いくつかのよりエキゾチックなキャラクターも含めたい場合は、いくつかの回避策を使用する必要があります。回避策の1つは、エスケープシーケンスです。このようにして、たとえば\n、文字列リテラルに2つの入力しやすい文字を追加するだけで、文字列の新しい行を表すことができます。したがって、'hello\nworld'文字列を印刷すると、単語は別々の行に印刷されます。とても便利です!

一方、エスケープシーケンスを含む文字列リテラルを作成したいが、Pythonで解釈させたくない場合があります。あなたはそれらが生であることを望みます。これらの例を見てください:

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

このような状況では、文字列リテラルの前に次のrような文字を付けるだけでかまいr'hello\nworld'ません。エスケープシーケンスはPythonによって解釈されません。文字列は、作成したとおりに印刷されます。

生の文字列リテラルは完全に「生」ではありませんか?

多くの人々は、「引用符で囲まれたものはすべてPythonによって無視される」という意味で、生の文字列リテラルが生であることを期待しています。それは真実ではありません。Pythonは引き続きすべてのエスケープシーケンスを認識しますが、エスケープシーケンスを解釈せず、変更されません。それは生の文字列リテラルがまだ有効な文字列リテラルでなければならないことを意味します

文字列リテラルの字句定義から:

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

裸の引用文字:を含む、'hello'world'またはバックスラッシュで終わる文字列リテラル(生かそうでないか)が無効であることは明らか'hello world\'です。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.