บอกได้ไหมว่าทำไมถึง'?\\\?'=='?\\\\?'
ให้True
? นั่นทำให้ฉันแทบคลั่งและหาคำตอบที่สมเหตุสมผลไม่ได้ ...
>>> list('?\\\?')
['?', '\\', '\\', '?']
>>> list('?\\\\?')
['?', '\\', '\\', '?']
บอกได้ไหมว่าทำไมถึง'?\\\?'=='?\\\\?'
ให้True
? นั่นทำให้ฉันแทบคลั่งและหาคำตอบที่สมเหตุสมผลไม่ได้ ...
>>> list('?\\\?')
['?', '\\', '\\', '?']
>>> list('?\\\\?')
['?', '\\', '\\', '?']
list()
แม้แต่:>>> '?\\\?'
'?\\\\?'
คำตอบ:
โดยทั่วไปเนื่องจาก python ผ่อนปรนเล็กน้อยในการประมวลผลแบ็กสแลช อ้างจากhttps://docs.python.org/2.0/ref/strings.html :
ซึ่งแตกต่างจากมาตรฐาน C ทั้งหมดลำดับหนีไม่รู้จักที่เหลืออยู่ในสายที่ไม่เปลี่ยนแปลงคือเครื่องหมายที่เหลืออยู่ในสตริง
(เน้นในต้นฉบับ)
ดังนั้นใน python ไม่ใช่ว่าแบ็กสแลชสามตัวจะมีค่าเท่ากับสี่ แต่เมื่อคุณติดตามแบ็กสแลชด้วยอักขระที่เหมือน?
กันทั้งสองจะมารวมกันเป็นสองอักขระเนื่องจาก\?
ไม่ใช่ลำดับการหลีกเลี่ยงที่รู้จัก
'escape''d'
) คุณไม่จำเป็นต้องจำตัวละครอื่น ๆ ที่นั่น!
เนื่องจากแบ็กสแลชทำหน้าที่เป็นอักขระหลีกสำหรับอักขระที่ตามหลังทันทีหากชุดค่าผสมแสดงลำดับการหลีกเลี่ยงที่ถูกต้อง โหลหรือดังนั้นลำดับหนีจะถูกแสดงไว้ที่นี่ พวกเขารวมถึงคนที่เห็นได้ชัดเช่นการขึ้นบรรทัดใหม่\n
แท็บแนวนอน\t
กลับสายการบิน\r
และคนที่คลุมเครือมากขึ้นเช่นอักขระ Unicode ตั้งชื่อโดยใช้\N{...}
เช่นซึ่งหมายถึงอักขระ\N{WAVY DASH}
Unicode \u3030
ประเด็นสำคัญคือถ้าไม่ทราบลำดับการหลีกเลี่ยงลำดับอักขระจะเหลืออยู่ในสตริงตามที่เป็นอยู่
ส่วนหนึ่งของปัญหาอาจเกิดจากเอาต์พุตของตัวแปล Python ทำให้คุณเข้าใจผิด เนื่องจากแบ็กสแลชจะถูกหลีกเลี่ยงเมื่อแสดง อย่างไรก็ตามหากคุณพิมพ์สตริงเหล่านั้นคุณจะเห็นแบ็กสแลชพิเศษหายไป
>>> '?\\\?'
'?\\\\?'
>>> print('?\\\?')
?\\?
>>> '?\\\?' == '?\\?' # I don't know why you think this is True???
False
>>> '?\\\?' == r'?\\?' # but if you use a raw string for '?\\?'
True
>>> '?\\\\?' == '?\\\?' # this is the same string... see below
True
สำหรับตัวอย่างเฉพาะของคุณในกรณีแรก'?\\\?'
ตัวแรกจะหลีกเลี่ยง\
แบ็กสแลชที่สองโดยเหลือแบ็กสแลชเดียว แต่แบ็กสแลชที่สามยังคงเป็นแบ็กสแลชเนื่องจาก\?
ไม่ใช่ลำดับการหลีกที่ถูกต้อง ?\\?
ดังนั้นสตริงที่เกิดคือ
สำหรับกรณีที่สองที่ทับขวาเป็นครั้งแรกที่สองหนีออกมาและทับขวาที่สามหนีออกมาที่สี่ซึ่งจะส่งผลในสตริง'?\\\\?'
?\\?
นั่นคือสาเหตุที่แบ็กสแลชสามตัวเหมือนกันกับสี่:
>>> '?\\\?' == '?\\\\?'
True
หากคุณต้องการสร้างสตริงที่มีแบ็กสแลช 3 ตัวคุณสามารถหลีกเลี่ยงแบ็กสแลชแต่ละตัวได้:
>>> '?\\\\\\?'
'?\\\\\\?'
>>> print('?\\\\\\?')
?\\\?
หรือคุณอาจพบว่าสตริง "ดิบ" เข้าใจได้ง่ายขึ้น:
>>> r'?\\\?'
'?\\\\\\?'
>>> print(r'?\\\?')
?\\\?
การเปลี่ยนการประมวลผลลำดับ Escape สำหรับสตริงลิเทอรัล ดูString Literalsสำหรับรายละเอียดเพิ่มเติม
'?\\\?'=='?\\?'
ให้False
ผมพิมพ์ผิด ควรจะ'?\\\?'=='?\\\\?'
เป็นตามที่คำถามระบุฉันได้แก้ไขแล้ว
เพราะ\x
ในสายอักขระเมื่อx
ไม่ได้เป็นหนึ่งในตัวละครที่ backslashable พิเศษเช่นn
, r
, t
, 0
ฯลฯ x
ประเมินสตริงที่มีเครื่องหมายและจากนั้น
>>> '\?'
'\\?'
จากหน้าการวิเคราะห์คำศัพท์ python ใต้ตัวอักษรสตริงที่: https://docs.python.org/2/reference/lexical_analysis.html
มีตารางที่แสดงรายการลำดับการหลีกเลี่ยงที่รู้จักทั้งหมด
\\ คือลำดับการหลีกเลี่ยงที่ === \
\? ไม่ใช่ลำดับการหลีกเลี่ยงและเป็น === \?
ดังนั้น '\\\\' คือ '\\' ตามด้วย '\\' ซึ่งก็คือ '\\' (สอง Escape \)
และ '\\\' คือ '\\' ตามด้วย '\' ซึ่งก็คือ '\\' เช่นกัน (หนึ่ง Escape \ และอีกหนึ่งดิบ \)
นอกจากนี้ควรสังเกตว่า python ไม่ได้แยกความแตกต่างระหว่างเครื่องหมายคำพูดเดี่ยวและคู่รอบตัวอักษรสตริงซึ่งแตกต่างจากภาษาอื่น ๆ
ดังนั้น "String" และ "String" จึงเหมือนกันทุกประการใน python ไม่มีผลต่อการตีความลำดับการหลีกเลี่ยง
คำตอบของ mhawke ค่อนข้างครอบคลุมฉันแค่อยากจะอธิบายใหม่ในรูปแบบที่กระชับและมีตัวอย่างเล็กน้อยที่แสดงพฤติกรรมนี้
ฉันเดาว่าสิ่งหนึ่งที่ต้องเพิ่มก็คือการหลีกเลี่ยงการประมวลผลการเคลื่อนที่จากซ้ายไปขวาเพื่อให้\n
ค้นหาแบ็กสแลชก่อนจากนั้นมองหาตัวละครที่จะหลบหนีจากนั้นค้นหาn
และหลบหนี \\n
ค้นหาแบ็กสแลชแรกค้นหาวินาทีและหลบหนีจากนั้นค้นหาn
และมองว่ามันเป็นตัวอักษร n; \?
ค้นหาแบ็กสแลชและมองหาอักขระเพื่อหลบหนีพบว่า?
สิ่งที่ไม่สามารถหลีกหนีได้และถือว่า\
เป็นแบ็กสแลชตามตัวอักษร
ดังที่ mhawke กล่าวไว้กุญแจสำคัญในที่นี้คือล่ามแบบโต้ตอบจะหนีเครื่องหมายแบ็กสแลชเมื่อแสดงสตริง ฉันเดาว่าเหตุผลก็คือเพื่อให้แน่ใจว่าสตริงข้อความที่คัดลอกจากล่ามไปยังตัวแก้ไขโค้ดเป็นสตริง python ที่ถูกต้อง อย่างไรก็ตามในกรณีนี้ค่าเผื่อความสะดวกนี้ทำให้เกิดความสับสน
>>> print('\?') # \? is not a valid escape code so backslash is left as-is
\?
>>> print('\\?') # \\ is a valid escape code, resulting in a single backslash
'\?'
>>> '\?' # same as first example except that interactive interpreter escapes the backslash
\\?
>>> '\\?' # same as second example, backslash is again escaped
\\?