Вообще-то это разные строки. Могут давать одинаковый результат, а могут и не давать.
Python:
class X():
def __ne__(self, other):
return False
def not_eq(x):
print(not x == 'val')
print(x != 'val')
# Могут давать
x = 1
not_eq(x)
# А могут и не давать
x = X()
not_eq(x)
Но если переменная x ссылается на встроенные типы Python, Ваши строки эквивалентны.
Просто операторы проверки равенства/неравенства == != вызывают методы классов __eq__ и __ne__, которые могут быть переопределены, в этом случае результаты проверки не гарантируются.