Bạn có thể cho tôi biết tại sao '?\\\?'=='?\\\\?'
lại cho True
? Điều đó khiến tôi phát điên và tôi không thể tìm ra câu trả lời hợp lý ...
>>> list('?\\\?')
['?', '\\', '\\', '?']
>>> list('?\\\\?')
['?', '\\', '\\', '?']
Bạn có thể cho tôi biết tại sao '?\\\?'=='?\\\\?'
lại cho True
? Điều đó khiến tôi phát điên và tôi không thể tìm ra câu trả lời hợp lý ...
>>> list('?\\\?')
['?', '\\', '\\', '?']
>>> list('?\\\\?')
['?', '\\', '\\', '?']
list()
chẵn:>>> '?\\\?'
'?\\\\?'
Câu trả lời:
Về cơ bản, vì python hơi khoan dung trong việc xử lý dấu gạch chéo ngược. Trích dẫn từ https://docs.python.org/2.0/ref/strings.html :
Không giống như Tiêu chuẩn C, tất cả các chuỗi thoát không được nhận dạng đều được giữ nguyên trong chuỗi, tức là, dấu gạch chéo ngược được để lại trong chuỗi .
(Nhấn mạnh trong bản gốc)
Do đó, trong python, không phải là ba dấu gạch chéo ngược bằng bốn, mà là khi bạn theo sau dấu gạch chéo ngược với một ký tự như ?
, cả hai kết hợp với nhau dưới dạng hai ký tự, vì \?
không phải là một chuỗi thoát được công nhận.
'escape''d'
:). Bạn thậm chí không cần phải nhớ các ký tự khác ở đó!
Điều này là do dấu gạch chéo ngược hoạt động như một ký tự thoát cho (các) ký tự ngay sau nó, nếu sự kết hợp đại diện cho một chuỗi thoát hợp lệ. Hàng tá trình tự thoát được liệt kê ở đây . Chúng bao gồm những cái rõ ràng như xuống dòng \n
, tab ngang \t
, vận chuyển trở lại \r
và những người mơ hồ hơn như các ký tự unicode tên sử dụng \N{...}
, ví dụ như \N{WAVY DASH}
đại diện cho ký tự unicode\u3030
. Tuy nhiên, điểm mấu chốt là nếu trình tự thoát không được biết thì chuỗi ký tự vẫn được giữ nguyên trong chuỗi.
Một phần của vấn đề cũng có thể là do đầu ra của trình thông dịch Python gây hiểu lầm cho bạn. Điều này là do dấu gạch chéo ngược được thoát ra khi hiển thị. Tuy nhiên, nếu bạn in các chuỗi đó, bạn sẽ thấy các dấu gạch chéo ngược thừa biến mất.
>>> '?\\\?'
'?\\\\?'
>>> 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
Đối với các ví dụ cụ thể của bạn, trong trường hợp đầu tiên '?\\\?'
, đầu tiên \
thoát khỏi dấu gạch chéo ngược thứ hai để lại một dấu gạch chéo ngược duy nhất, nhưng dấu gạch chéo ngược thứ ba vẫn là dấu gạch chéo ngược vì \?
không phải là chuỗi thoát hợp lệ. Do đó, chuỗi kết quả là ?\\?
.
Đối với trường hợp thứ hai '?\\\\?'
, dấu gạch chéo ngược đầu tiên thoát khỏi dấu gạch chéo ngược thứ hai và dấu gạch chéo ngược thứ ba thoát khỏi dấu gạch chéo ngược thứ tư dẫn đến chuỗi ?\\?
.
Vì vậy, đó là lý do tại sao ba dấu gạch chéo ngược giống như bốn:
>>> '?\\\?' == '?\\\\?'
True
Nếu bạn muốn tạo một chuỗi có 3 dấu gạch chéo ngược, bạn có thể thoát từng dấu gạch chéo ngược:
>>> '?\\\\\\?'
'?\\\\\\?'
>>> print('?\\\\\\?')
?\\\?
hoặc bạn có thể thấy chuỗi "thô" dễ hiểu hơn:
>>> r'?\\\?'
'?\\\\\\?'
>>> print(r'?\\\?')
?\\\?
Đây là lượt xử lý trình tự thoát cho chuỗi ký tự. Xem String Literals để biết thêm chi tiết.
'?\\\?'=='?\\?'
cho đúng False
, tôi đã gõ sai. Đó phải là '?\\\?'=='?\\\\?'
như câu hỏi chỉ ra, tôi đã sửa nó.
Từ trang phân tích từ vựng python trong chuỗi ký tự tại: https://docs.python.org/2/reference/lexical_analysis.html
Có một bảng liệt kê tất cả các chuỗi thoát được công nhận.
\\ là một chuỗi thoát === \
\? không phải là một chuỗi thoát và là === \?
vì vậy '\\\\' là '\\' theo sau là '\\' là '\\' (hai thoát \)
và '\\\' là '\\' theo sau là '\' cũng là '\\' (một thoát \ và một nguyên \)
Ngoài ra, cần lưu ý rằng python không phân biệt giữa dấu ngoặc kép đơn và dấu ngoặc kép xung quanh một chuỗi ký tự, không giống như một số ngôn ngữ khác.
Vì vậy, 'String' và "String" hoàn toàn giống nhau trong python, chúng không ảnh hưởng đến việc giải thích các chuỗi thoát.
Câu trả lời của mhawke bao hàm khá nhiều vấn đề, tôi chỉ muốn trình bày lại nó dưới dạng ngắn gọn hơn và với các ví dụ tối thiểu minh họa hành vi này.
Tôi đoán một điều cần thêm là xử lý thoát di chuyển từ trái sang phải, vì vậy \n
đầu tiên tìm dấu gạch chéo ngược và sau đó tìm kiếm một nhân vật để thoát, sau đó tìm n
và thoát khỏi nó; \\n
tìm dấu gạch chéo ngược đầu tiên, tìm thứ hai và thoát khỏi nó, sau đó tìm n
và coi nó như một chữ n; \?
tìm dấu gạch chéo ngược và tìm một ký tự để thoát, tìm ký tự ?
không thể thoát và vì vậy được coi \
như một dấu gạch chéo ngược theo nghĩa đen.
Như mhawke đã lưu ý, chìa khóa ở đây là trình thông dịch tương tác thoát khỏi dấu gạch chéo ngược khi hiển thị một chuỗi. Tôi đoán lý do cho điều đó là để đảm bảo rằng các chuỗi văn bản được sao chép từ trình thông dịch vào trình soạn thảo mã là các chuỗi python hợp lệ. Tuy nhiên, trong trường hợp khoản trợ cấp này để thuận tiện gây ra sự nhầm lẫn.
>>> 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
\\?