То, что вы видите, представляет собой представление my_string, созданное с помощью метода __repr__(). Если вы распечатаете его, вы увидите, что на самом деле у вас есть одна обратная косая черта, как вы и предполагали:
>>> print(my_string)
why\does\it\happen?
Вы можете получить стандартное представление строки (или любого другого объекта) с помощью встроенной функции repr():
Python представляет обратную косую черту в строках как \\, потому что обратная косая черта является escape-символом - например, \n представляет новую строку, а \t представляет вкладку.
Это может иногда вызвать у вас неприятности:
>>> print("this\text\is\not\what\it\seems")
this ext\is
ot\what\it\seems
Из-за этого должен быть способ сказать Python, что вы действительно хотите, чтобы два символа \n, а не новая строка, и вы делаете это, экранируя обратную косую черту, с другой:
Когда Python возвращает представление строки, он играет безопасно, избегая всех обратных косых черт (даже если они в противном случае не были бы частью escape-последовательности) и того, что вы видите. Однако сама строка содержит только одну обратную косую черту.
Более подробную информацию о строковых литералах Python можно найти по литералам String и Bytes в документации Python.