You could increase the conditions used for each character, e.g.,
ns =''.join([i for i in string if i == " " or i.isalpha()])
But there is a problem with sequences like "666 " that leave an extra space in the text.
Instead, you could use a regex to break the string down into a list of words and intervening non-word text. Filter out the stuff you don't want, and then remove any items where the word itself went to zero size.
import re
string = "Hello! I have a Big!!! problem 666 is not a good number__$"
tmp = []
for word, other in re.findall(r"(\w+)([^\w]*)", string):
# strip non-alpha
word = "".join(c for c in word if c.isalpha())
# preserve only spaces
other = "".join(c for c in other if c == " ")
# only add if word still exists
if word:
tmp.append(word + other)
ns = "".join(tmp)
print(ns)
Output
Hello I have a Big problem is not a good number