Не могли б ви сказати мені, чому '?\\\?'=='?\\\\?'дає True? Це зводить мене з розуму, і я не можу знайти розумної відповіді ...
>>> list('?\\\?')
['?', '\\', '\\', '?']
>>> list('?\\\\?')
['?', '\\', '\\', '?']
Не могли б ви сказати мені, чому '?\\\?'=='?\\\\?'дає True? Це зводить мене з розуму, і я не можу знайти розумної відповіді ...
>>> list('?\\\?')
['?', '\\', '\\', '?']
>>> list('?\\\\?')
['?', '\\', '\\', '?']
list()навіть:>>> '?\\\?' '?\\\\?'
Відповіді:
В основному тому, що python дещо поблажливий при обробці зворотних рисок. Посилання з https://docs.python.org/2.0/ref/strings.html :
На відміну від стандарту С, усі нерозпізнані послідовності екрану залишаються в рядку без змін, тобто зворотна коса риса залишається в рядку .
(Упор в оригіналі)
Отже, у 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'?\\\?')
?\\\?
Це призводить до обробки вхідної послідовності для рядкового літералу. Докладніше див. У розділі String Literals .
'?\\\?'=='?\\?'дає False, я неправильно набраний його. Це має бути, '?\\\?'=='?\\\\?'як вказує питання, я це виправив.
Зі сторінки лексичного аналізу python під рядковими літералами за адресою: https://docs.python.org/2/reference/lexical_analysis.html
Існує таблиця, в якій перелічені всі розпізнані послідовності екранування.
\\ - це послідовність екрану, яка === \
\? не є послідовністю виходу та є === \?
отже, "\\\\" - це "\\", за яким слідує "\\", тобто "\\" (два втекли \)
і '\\\' - це '\\', за яким слідує '\', який також є '\\' (один вийшов \ і один сирий \)
також слід зазначити, що python не розрізняє одинарні та подвійні лапки навколо рядкового літералу, на відміну від деяких інших мов.
Отже, "Рядок" і "Рядок" - це те саме, що в 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
\\?