Password Generator with injected password model I'm getting started with Python and one of the beginner projects to learn the language was a password generator (one of the dozens already in CodeReview). I have a C# and JS background so I want to make sure I'm doing things the Python way.
Technically the include_punctuation and include_digits properties could be omitted and the exclusion list would be a custom concat of strings.digits+strings.punctuation.
The reasoning behind the PasswordModel is that any component that has an API of charset and length is a valid model. That would mean we could create a MemorablePasswordModel for passwords such as &quot;apple truck butterfly postcard&quot; with a clean and separate model.
from random import choice
from string import digits, ascii_letters, punctuation


def filter_exclusions(items, exclusions):
    result = []
    for i in items:
        if i not in exclusions:
            result.append(i)

    return result


class PasswordModel:
    def __init__(self, length=8, include_symbols=True, include_digits=True, exclusion_list=&quot;&quot;):
        self.exclusion_list = list(exclusion_list)
        self.length = length
        self.include_symbols = include_symbols
        self.include_digits = include_digits

    def charset(self) -&gt; str:
        chars = [ascii_letters]

        if self.include_symbols:
            chars.append(punctuation)
        if self.include_digits:
            chars.append(digits)

        return &quot;&quot;.join(filter_exclusions(&quot;&quot;.join(chars), self.exclusion_list))


class PasswordGenerator:
    def __init__(self, password_model=PasswordModel()):
        self.model = password_model

    def generate(self) -&gt; str:
        charset = self.model.charset()
        return &quot;&quot;.join(choice(charset) for _ in range(self.model.length))


# Test it out
model = PasswordModel(length=24, exclusion_list=&quot;\\/@%&quot;)
gen = PasswordGenerator()

print(gen.generate())

Questions

Is there a cleaner way to &quot;include&quot; symbols and digits, I just appended them to a list.
Is there anything built-in to exclude one list from another?
Is there a cleaner way to &quot;include&quot; symbols and digits, I just appended them to a list.

Cast (rather than wrap) ascii_letters etc. to a set.

Is there anything built-in to exclude one list from another?

Yes - don't use lists; use sets and apply set subtraction.
Otherwise: if you perform a cursory scan of this site for Python-based password generators you will hear some of these same points, but -

Do not use random; use the secrets module to generate secure random numbers
PasswordGenerator being its own separate class does not make sense; it doesn't offer anything over generate so generate can be a free function or more likely a method on PasswordModel
charset would be better to return a set than a str
Maybe exclusion_list is being accepted as a string due to the valid concern that mutables (lists, etc.) should not be made parameter defaults. That's fine, though a type hint exclusion_list: Iterable[str] = &quot;&quot; should make it clear that other iterables are acceptable, such as a set or tuple.