Почему is работает не так, как ожидается?
Ладно
a = 'af' Инициализируем ПЕРВУЮ переменную А = АФ  идентиф=1
b = 'a' Инициализируем ВТОРУЮ переменную Б= А     идентиф=2
b += 'f' Инициализируем ТРЕТЬЮ переменную Б = А + Ф  идентиф=3
# А все почему? Строка - НЕИЗМЕНЯЕМЫЙ ТИП
print(a is b)
>>> False
a = 5
b = 2
b += 3
# Тоже самое но, в питоне числа до 255 КЕШИРУЮТСЯ и 50 is 50 и 255 is 255
print(a is b)
>>> True

А тут,
a = 'af'       #Инициализируем ПЕРВУЮ (ОНА ИДЕТ В КЕШ) А = АФ
b = 'a' + 'f'  #Инициализируем ВТОРУЮ интерпретатор не тупой и Б = ТОЖЕ АФ (а так как аф есть в кеше Б получает ссылку на ту же память)

print(a is b)
>>> True

Где читать? Гугл-
Изменяемые неизменяемые типы,
Потому что is это сравнение на уровне "а тот ли это самый объект".
Понятно, что эти строки - разные объекты, поэтому сравнивать нужно через ==
a = 'af'
b = 'a'
b += 'f'
print (a is b)
>>> False
print (a == b)
>>> True

Иногда питон может экономить память и если видит что переменной задается тоже самое значение изначально, он использует уже существующий объект, что может вводить тебя иногда в заблуждение.
Но операция b += 'f' не может изменить объект b, поэтому тут создается новый, другой объект.