То, что вы видите, - это представление, my_string созданное его __repr__() методом. Если вы распечатаете ее, то увидите, что на самом деле у вас получилась одиночная обратная косая черта, как вы и предполагали:
>>> print(my_string) why\does\it\happen?
Приведенная ниже строка содержит три символа, а не четыре:
>>> 'a\\b' 'a\\b' >>> len('a\\b') 3
Вы можете получить стандартное представление строки (или любого другого объекта) с помощью repr() встроенной функции:
Python представляет обратную косую черту в строках как \\ потому что обратная косая черта является управляющим символом - например, \n представляет собой перевод строки, а \t представляет табуляцию.
Иногда это может привести к неприятностям:
>>> print("this\text\is\not\what\it\seems") this ext\is ot\what\it\seems
Из-за этого должен быть способ сообщить Python, что вам действительно нужны два символа \n, а не перевод строки, и вы делаете это, экранируя саму обратную косую черту другой:
Когда Python возвращает представление строки, он работает безопасно, экранируя все обратные косые черты (даже если в противном случае они не были бы частью escape-последовательности), и это то, что вы видите. Однако сама строка содержит только одну обратную косую черту.
Дополнительную информацию о строковых литералах Python можно найти по адресу: Строковые и байтовые литералы в документации Python.
Но есть дополнительная проблема: в будущем использование неопределенной escape-последовательности типа \d вместо буквенной обратной косой черты, за которой следует d, будет ошибкой. Итак, вместо того, чтобы просто считать удачей, что ваша строка использовала \d вместо \t, поэтому она сделала то, что вы, вероятно, хотели, она определенно не будет делать то, что вы хотите.
Начиная с версии 3.6, это вызывает DeprecationWarning, хотя большинство людей их не видят. Начиная с версии 3.12, это вызывает SyntaxWarning. Это станет SyntaxError в какой-нибудь будущей версии, согласно документации по escape-последовательностям.
Во многих других языках, включая C, использование обратной косой черты, которая не запускает escape-последовательность, означает, что обратная косая черта игнорируется.
В нескольких языках, включая Python, обратная косая черта, которая не запускает escape-последовательность, является буквальной обратной косой чертой.
В некоторых языках, чтобы избежать путаницы в том, является ли язык похожим на C или Python, и чтобы избежать проблемы с \Foo работает, но \foo не работает, обратная косая черта, которая не запускает escape-последовательность, является незаконной.