แฟล็กสตริง“ u” และ“ r” ทำอะไรกันแน่และสตริงตัวอักษรดิบคืออะไร


652

ในขณะที่ถามคำถามนี้ฉันรู้ว่าฉันไม่รู้จักเกี่ยวกับสตริงดิบมากนัก สำหรับใครบางคนที่อ้างว่าเป็นเทรนเนอร์ของ Django นี่มันแย่มาก

ฉันรู้ว่าการเข้ารหัสคืออะไรและฉันรู้ว่าตัวu''เองทำอะไรคนเดียวตั้งแต่ฉันได้รับ Unicode

  • แต่จะr''ทำอะไรกันแน่? มันส่งผลสตริงชนิดใด

  • และเหนือสิ่งอื่นใดสิ่งที่ห่าur''ทำอะไร?

  • ในที่สุดมีวิธีที่เชื่อถือได้เพื่อกลับไปจากสาย Unicode เพื่อสตริงดิบง่าย ๆ ?

  • อ่าและถ้าระบบของคุณและชุดตัวแก้ไขข้อความถูกตั้งค่าเป็น UTF-8 จะu''ทำอะไรได้จริงหรือ

คำตอบ:


683

มีไม่มาก ๆ "ดิบสตริง "; มีตัวอักษรสตริงดิบซึ่งเป็นตัวอักษรสตริงที่มีการทำเครื่องหมายโดย'r'ก่อนที่จะพูดเปิด

"สตริงตัวอักษรดิบ" เป็นไวยากรณ์ที่แตกต่างกันเล็กน้อยสำหรับสตริงตัวอักษรซึ่งเป็นเครื่องหมายแบ็กสแลช\จะถูกนำมาเป็นความหมาย "เพียงแค่แบ็กสแลช" (ยกเว้นเมื่อมันมาก่อนคำพูดที่จะยุติตัวอักษร) - ไม่มี "escape sequences" เพื่อแสดงบรรทัดใหม่แท็บ backspaces แบบฟอร์มฟีดและอื่น ๆ ในตัวอักษรสตริงปกติเครื่องหมายแบ็กสแลชแต่ละอันจะต้องถูกเพิ่มเป็นสองเท่าเพื่อหลีกเลี่ยงการถูกใช้เป็นจุดเริ่มต้นของลำดับการยกเว้น

ตัวแปรไวยากรณ์นี้มีอยู่เป็นส่วนใหญ่เนื่องจากไวยากรณ์ของรูปแบบการแสดงออกปกติหนักกับแบ็กสแลช (แต่ไม่สิ้นสุดดังนั้นประโยค "ยกเว้น" ด้านบนไม่สำคัญ) และมันดูดีขึ้นเล็กน้อยเมื่อคุณหลีกเลี่ยงการเพิ่มแต่ละคู่ - - นั่นคือทั้งหมดที่ นอกจากนี้ยังได้รับความนิยมในการแสดงพา ธ ไฟล์ของ Windows ดั้งเดิม (ด้วยแบ็กสแลชแทนที่จะเป็นสแลชปกติเหมือนบนแพลตฟอร์มอื่น ๆ ) แต่ก็ไม่ค่อยมีความจำเป็นมากนัก (เนื่องจากสแลชปกติส่วนใหญ่ทำงานได้ดีบน Windows เช่นกัน) ข้างบน).

r'...'เป็นสตริงไบต์ (ในหลาม 2 *) ur'...'เป็นสตริง Unicode (อีกครั้งในหลาม 2 *) และอื่น ๆ ของสามชนิดอ้างว่ายังผลิตประเภทเดียวกันของสตริง (ดังนั้นสำหรับตัวอย่างr'...', r'''...''', r"...", r"""..."""เป็นสตริงไบต์ทั้งหมดและอื่น ๆ )

ไม่แน่ใจว่าสิ่งที่คุณหมายถึงโดย " กลับไป " - ไม่มีทิศทางกลับไปกลับมาเพราะไม่มีประเภทสตริงดิบมันเป็นเพียงไวยากรณ์ทางเลือกในการแสดงวัตถุสตริงปกติอย่างสมบูรณ์ไบต์หรือ Unicode เช่นที่พวกเขาอาจจะ

และใช่ในหลาม 2. * u'...' เป็นแน่นอนเสมอแตกต่างจากเพียง'...'- อดีตเป็นสตริง Unicode หลังเป็นสตริงไบต์ สิ่งที่เข้ารหัสตัวอักษรอาจจะแสดงออกมาเป็นปัญหามุมฉากอย่างสมบูรณ์

เช่นพิจารณา (Python 2.6):

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

แน่นอนว่าวัตถุ Unicode นั้นใช้พื้นที่หน่วยความจำมากกว่า (แตกต่างกันเล็กน้อยสำหรับสตริงที่สั้นมากชัด ;-)


6
การทำความเข้าใจกับ "r" นั้นไม่ได้หมายความถึงปัญหาการเข้ารหัสหรือประเภทใด ๆ มันง่ายกว่ามาก
E-satis

23
โปรดทราบว่า ru "C: \ foo \ unstable" จะล้มเหลวเนื่องจาก \ u เป็นลำดับการหลบหนีแบบ Unicode ในโหมด ru โหมด r ไม่มี \ u
เคอร์ติส Yallop

26
โปรดทราบว่าuและrไม่ได้สลับกัน: ur'str'ทำงานru'str'ไม่ได้ (อย่างน้อยใน ipython 2.7.2 สำหรับ win7)
RafiK

7
เพิ่งผ่านการทดสอบrสตริงและสังเกตเห็นว่าถ้า\ เป็นตัวละครที่ผ่านมาจะไม่ถูกนำมาเป็นตัวอักษร SyntaxError: EOL while scanning string literalแต่แทนที่จะหนีอ้างปิดที่ก่อให้เกิด ดังนั้น\\ จะต้องใช้สำหรับอินสแตนซ์สุดท้ายของ\ ในสตริงใด ๆ ที่ลงท้ายด้วยแบ็กสแลช
Enteleform

1
python 3.x - sys.getsizeof('cioa') == sys.getsizeof(r'cioa') == sys.getsizeof(u'cioa')(Ubuntu 16.04 พร้อม UTF8 lang) ในทำนองเดียวกัน, type('cioa') == type(r'cioa') == type(u'cioa'). แต่การแก้ไขสตริงดิบสร้างความแตกต่างดังนั้นsys.getsizeof('\ncioa') == sys.getsizeof(u'\ncioa') != sys.getsizeof(r'\ncioa')
Darren Weber

177

มีสองประเภทของสตริงในหลามคือแบบดั้งเดิมstrและแบบใหม่unicodeประเภท หากคุณพิมพ์สตริงตัวอักษรโดยไม่มีuส่วนหน้าคุณจะได้รับstrชนิดเก่าที่เก็บอักขระ 8 บิตและuด้านหน้าคุณจะได้รับunicodeชนิดที่ใหม่กว่าซึ่งสามารถเก็บอักขระ Unicode ใด ๆ ได้

rไม่เปลี่ยนชนิดที่ทุกคนมันก็เปลี่ยนแปลงวิธีการที่แท้จริงสตริงถูกตีความ หากไม่มีrเครื่องหมายแบ็กสแลชจะถือว่าเป็นอักขระยกเว้น ด้วยrเครื่องหมายแบ็กสแลชจะถือว่าเป็นตัวอักษร ไม่ว่าจะด้วยวิธีใดประเภทเดียวกัน

ur เป็นสายอักขระ Unicode ที่แบ็กสแลชเป็นแบ็คสแลชที่แท้จริงไม่ใช่ส่วนหนึ่งของรหัสยกเว้น

คุณสามารถลองแปลงสตริง Unicode เป็นสตริงเก่าโดยใช้str()ฟังก์ชั่น แต่ถ้ามีอักขระ Unicode ใด ๆ ที่ไม่สามารถแสดงในสตริงเก่าได้คุณจะได้รับข้อยกเว้น คุณสามารถแทนที่พวกเขาด้วยเครื่องหมายคำถามก่อนหากคุณต้องการ แต่แน่นอนว่าสิ่งนี้จะทำให้ตัวละครเหล่านั้นไม่สามารถอ่านได้ ไม่แนะนำให้ใช้strชนิดถ้าคุณต้องการจัดการอักขระ Unicode อย่างถูกต้อง


ขอบคุณได้รับการยอมรับ อย่างที่ฉันพูดฉันรู้ว่ายูนิโค้ดคืออะไรฉันไม่รู้ว่า "r" หมายถึงอะไรและอะไรคือการรวมกันของ "u" และ "r" ฉันรู้ดีกว่ารู้ดีไชโย
E-satis

6
แบ็กสแลชไม่ถือเป็นตัวอักษรในสตริงตัวอักษรดิบซึ่งเป็นสาเหตุของr"\"ข้อผิดพลาดทางไวยากรณ์

4
ใช้กับ Python 2 เท่านั้น
PaulMcG

60

'raw string'หมายถึงมันถูกเก็บไว้ตามที่ปรากฏ ยกตัวอย่างเช่น'\'เป็นเพียงทับขวาแทนการหนี


3
... เว้นเสียแต่ว่ามันจะเป็นตัวอักษรตัวสุดท้ายของสตริงซึ่งในกรณีนี้มันจะหนีจากเครื่องหมายคำพูดปิด
jez

36

A "U" คำนำหน้าหมายถึงค่าที่มีประเภทมากกว่าunicodestr

ตัวอักษรสตริงดิบที่มีคำนำหน้า "r" ให้หลีกเลี่ยง escape sequences ใด ๆ ที่อยู่ภายในดังนั้นlen(r"\n")คือ 2 เนื่องจากพวกมันหนี escape sequences คุณไม่สามารถจบตัวอักษรสตริงด้วย backslash เดียว: นั่นไม่ใช่ลำดับ escape ที่ถูกต้อง (เช่นr"\")

"ดิบ" ไม่ได้เป็นส่วนหนึ่งของประเภท แต่เป็นเพียงวิธีเดียวในการแสดงค่า ยกตัวอย่างเช่น"\\n"และr"\n"มีค่าเหมือนกันเช่นเดียว32, 0x20และ0b100000เหมือนกัน

คุณสามารถมียูนิโค้ดสตริงตัวอักษรดิบ:

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

การเข้ารหัสไฟล์ต้นฉบับเพียงกำหนดวิธีการตีความไฟล์ต้นฉบับ แต่จะไม่มีผลต่อการแสดงออกหรือประเภทอื่น อย่างไรก็ตามขอแนะนำให้หลีกเลี่ยงรหัสที่การเข้ารหัสอื่นที่ไม่ใช่ ASCII จะเปลี่ยนความหมาย:

ไฟล์ที่ใช้ ASCII (หรือ UTF-8 สำหรับ Python 3.0) ไม่ควรมีการเข้ารหัสคุกกี้ ควรใช้ Latin-1 (หรือ UTF-8) เมื่อความคิดเห็นหรือ docstring จำเป็นต้องพูดถึงชื่อผู้แต่งที่ต้องใช้ภาษาละติน -1 มิฉะนั้นการใช้ \ x, \ u หรือ \ U escapes เป็นวิธีที่ต้องการรวมข้อมูลที่ไม่ใช่ ASCII ในตัวอักษรสตริง


30

ผมขออธิบายง่ายๆ: ใน python 2 คุณสามารถเก็บสตริงได้ 2 แบบ

คนแรกคือASCIIซึ่งเป็นประเภทSTRในหลามมันใช้ 1 ไบต์ของหน่วยความจำ (256 ตัวอักษรส่วนใหญ่จะเก็บตัวอักษรภาษาอังกฤษและสัญลักษณ์ง่าย ๆ )

ประเภทที่สองคือUNICODEซึ่งเป็นประเภทUnicodeในหลาม Unicode เก็บทุกภาษา

โดยปกติแล้วไพ ธ อนจะชอบประเภทstrแต่ถ้าคุณต้องการเก็บสตริงในรูปแบบunicodeคุณสามารถวางuไว้หน้าข้อความเช่นu'text 'หรือคุณสามารถทำได้โดยเรียกunicode (' text ')

ดังนั้นยูเป็นเพียงวิธีที่สั้น ๆ เพื่อเรียกฟังก์ชั่นที่จะโยนSTRเพื่อUnicode แค่นั้นแหละ!

ตอนนี้อาร์ส่วนที่คุณใส่ไว้ในด้านหน้าของข้อความที่จะบอกคอมพิวเตอร์ว่าข้อความนี้เป็นข้อความดิบทับขวาไม่ควรจะเป็นตัวละครที่หลบหนี r '\ n'จะไม่สร้างอักขระขึ้นบรรทัดใหม่ มันเป็นเพียงข้อความธรรมดาที่มี 2 ตัวอักษร

หากคุณต้องการแปลงstrเป็นunicodeและใส่ข้อความดิบไว้ในนั้นให้ใช้urเพราะruจะทำให้เกิดข้อผิดพลาด

ตอนนี้ส่วนสำคัญ:

คุณไม่สามารถเก็บแบ็กสแลชหนึ่งรายการโดยใช้rมันเป็นข้อยกเว้นเพียงอย่างเดียว ดังนั้นรหัสนี้จะสร้างข้อผิดพลาด: r '\'

ในการจัดเก็บเครื่องหมายแบ็กสแลช (หนึ่งอัน) คุณต้องใช้'\\'

หากคุณต้องการเก็บมากกว่า 1 ตัวอักษรคุณยังสามารถใช้rเช่นr '\\'จะสร้างแบ็กสแลช 2 ตัวตามที่คุณคาดไว้

ฉันไม่ทราบสาเหตุที่rไม่ทำงานกับแบ็กสแลชที่เก็บข้อมูลเดียว แต่ยังไม่มีใครอธิบายเหตุผล ฉันหวังว่ามันจะเป็นข้อผิดพลาด


9
คุณจะสังเกตเห็นว่าไม่เพียง แต่r'\'เป็นสิ่งผิดกฎหมายคุณยังไม่สามารถวางเดี่ยว'\'ที่ส่วนท้ายของสตริงได้ เช่นเดียวr'xxxxxx\'กับสตริงที่ผิดกฎหมาย
ดำน้ำ

หลาม 3 เกี่ยวกับอะไร?
Krissh

1
@Krissh สตริง python 3 ทั้งหมดรองรับ Unicode strประเภทของมันจะเป็น อ่านเพิ่มเติมเพื่อความเข้าใจที่ดีขึ้นที่นี่: medium.com/better-programming/…
off99555

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 yประเมินเป็น True ใน python3 หรือไม่
Habeeb Perwad

5
@HabeebPerwad ว่าเป็นเพราะสตริง interning คุณไม่ควรพึ่งพาความจริงที่x is yเกิดขึ้นกับการประเมินTrueเนื่องจากการฝึกงาน ใช้แทนx == y(หากคุณไม่ได้ตรวจสอบว่า x และ y เป็นวัตถุเดียวกันที่เก็บไว้ในตำแหน่งหน่วยความจำเดียวนั่นคือ)
Lucubrator

4

ตัวอักษรของสตริง Unicode

ตัวอักษรสตริง Unicode (ตัวอักษรสตริงนำหน้าด้วยu) จะไม่ถูกใช้ใน Python 3 อีกต่อไปพวกมันยังใช้งานได้ แต่เพื่อความเข้ากันได้กับ Python 2

ตัวอักษรสตริงดิบ

หากคุณต้องการที่จะสร้างสตริงตัวอักษรประกอบด้วยตัวอักษรได้อย่างง่ายดายเพียง typable 'hello world'เช่นตัวอักษรภาษาอังกฤษหรือตัวเลขที่คุณสามารถพิมพ์พวกเขา แต่ถ้าคุณต้องการที่จะรวมตัวละครที่แปลกใหม่เข้าด้วยกันคุณจะต้องใช้วิธีแก้ปัญหาบางอย่าง หนึ่งในวิธีการแก้ปัญหาที่มีลำดับหนี ตัวอย่างเช่นคุณสามารถแสดงบรรทัดใหม่ในสตริงของคุณได้ง่ายๆโดยเพิ่มอักขระที่พิมพ์ได้สองตัว\nลงในสตริงของคุณ ดังนั้นเมื่อคุณพิมพ์'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 ยังคงจดจำลำดับการหลบหนีทั้งหมด แต่มันไม่ได้แปลความหมายมันจะทำให้พวกมันไม่เปลี่ยนแปลงแทน ก็หมายความว่าตัวอักษรของสตริงดิบยังคงต้องตัวอักษรของสตริงที่ถูกต้อง

จากคำศัพท์ของสตริงตัวอักษร:

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.