unique username generator
Areas to fix/improve:

Namings

The function names like split_full_name_and_filter_stop_word, check_and_update_username_to_unique and alike are considered as anti-patterns for function naming.
run_and_fly or think_or_talk like names point to ambiguity or excessive responsibilities assigned to a function.A function should have a concrete responsibility. Therefore, you need to analyze those functions and apply whether Rename function or Extract function (in your case - split a function into several functions each with separate responsibility) technique.

Some variable and function names are too verbose:
name_words --> just names
get_name_from_list_of_words --> just compose_username
list_of_words --> just a plural words
unique_name_list --> just unique_names 



def generate_username(self, full_name, size, unique_name_list=None) method.


to avoid passing the same unique_name_list across multiple methods - it's good to pass it into UniqueNameGenerator constructor at once.
full_name = re.sub("[^\sa-zA-Z]+", "", full_name). In case if full_name happened to be empty, to avoid redundant calls of subsequent functions - it's good to add a check for that:

...
full_name = re.sub("[^\sa-z]+", "", full_name.strip(), re.I)
if not full_name:
    raise ValueError(f'Incorrect full name `{full_name}`')

either of these complements:

if self.suffix:
    username = username + self.suffix
if self.prefix:
    username = self.prefix + username


can throw TypeError in case if caller would pass non-string argument for prefix or suffix.Instead, use flexible f-string formatting:

username = f'{self.prefix}{username}{self.suffix}'





def split_full_name_and_filter_stop_word(self, full_name, size) method


the function name is better named as filter_valid_words or select_valid_words (or alike)
" ".join(full_name.split(" ")).split() - this looks like a "5-wheel bicycle that circles rounds instead of going straight".Simply words = full_name.split()
the whole construction:

words_considered = []
for word in name_words:
    ignore_word = False
    if word.lower() in self.stop_words:
        ignore_word = True
    if not ignore_word:
        words_considered.append(word)


is a verbose "invention" of a simple list comprehension with if constraint:

valid_words = [w for w in words if w.lower() not in self.stop_words]


The restructured function would look as:

def filter_valid_words(self, full_name, size):
    words = full_name.split()
    if len(words) &gt; size:
        words = words[:size]

    return [w for w in words if w.lower() not in self.stop_words]