Я тут вообще не вижу никакого удаления скобок.
Заменяется на пробел весь текст между первой закрывающей скобкой и последней открывающей, включая их. Причём, это делается максимально неэффективным способом. И цикл не нужен, ко второй итерации нечего будет удалять. В указанном в вопросе тексте будет удалена эта часть: ) лишнее) прошлогодний снег (
Вот небольшой говнокодец, решающий задачу: from re import split
a = "Падал(лишнее (лишнее) лишнее) прошлогодний снег (лишнее)"
r = r'\([^())]+\)'
s = split(r, a)
while len(s) > 1:
a = ' '.join(s)
s = split(r, a)
print(a)
Хотя, я думаю, что это можно сделать однопроходным алгоритмом. Но его придётся самому писать, а тут - готовые регулярки.
Впрочем, вот: a = "Падал(лишнее (лишнее) лишнее) прошлогодний снег (лишнее)"
b, e, l = -1, 0, 0
s = ""
for i in range(len(a)):
if a == '(':
l += 1
if l == 1: b = i
elif a == ')':
if l == 1:
s += a[e:b] + ' '
b, e = -1, i + 1
l = max(l, 1) - 1
if b >= 0:
s += a[e:b]
print(s)
Основная ошибка в том, что метод replace, цитирую описание, «Return a copy of the string...». Поэтому все действия в цикле производятся с неизменной начальной строкой, что приводит к бесконечному циклу.
Простейший вариант решения: присваивать результат replace самой строке: while "(" in a and ")" in a:
b = a.rfind("(")
c = a.find(")",b)
a = a.replace(a[b:c+1], " ")
print(a) Хочу также обратить внимание, что replace заменяет не диапазон, а подстроку, причём по умолчанию все вхождения подстроки. Это легко увидеть, если внести вызов print в цикл (кстати, этот метод тестовой отладки помог бы сразу понять, что цикл не изменяет строку).