'Add key:value to dictionary if variable is not None

I have a function clans(), that accepts 8 arguments. I need to add key and value pair to dictionary if argument is not None. There is my solution:

def clans(self, name: str = None, warFrequency: str = None, location: str = None,
            minMembers: int = None, maxMembers: int = None,
            minClanPoints: int = None, minClanLevel: int = None,
            labels: list[str] = None):
    params = {} # <- the dictionary to add to

    # very much if-conditions
    if name is not None:
        params['name'] = name
    if warFrequency is not None:
        params['warFrequency'] = warFrequency
    ... # <- other function arguments and if conditions
    if labels is not None:
        params['labels'] = labels
    
    return params

I think it is not the most optimal solution due to the large amount of code and poor readability, how can I improve that code? I have an idea like (but I dont know how to realize it):

params = {}
for arg in args: # <- args is list of function arguments
    if arg is not None:
        params[arg.key()] = arg.value() # <- arg.key() is argument name, arg.value() is value


Solution 1:[1]

You might reconsider your strategy.

It's better to have a dictionary with a value of None for certain keys than an inconsistent dictionary where some keys might not exist.

So if you allow the function clans to be called with some missing info, just create that key and assign a value of none. That's perfectly fine since maybe you don't have that info at this point.

Later on you can have a function that updates those values, so you just reassign a dictionary key which already exist and you don't have to worry about those keys not existing.

So, I would do something like:

def clans(self, name: str = None, warFrequency: str = None, location: str = None,
            minMembers: int = None, maxMembers: int = None,
            minClanPoints: int = None, minClanLevel: int = None,
            labels: list[str] = None):
    myKeys = ["name", "warFrequency", "location", "minMembers", "maxMembers", "minClanPoints", "minClanLevel"]
    myValues = [name, warFrequency, location, minMembers, maxMembers, minClanPoints, minClanLevel]
    return dict(zip(myKeys, myValues))

This way you have a consistent dictionary. You will have to check later if some values are None.

Creating a dictionary with missing keys will force you to check if they exist in a future, instead not you can just check if they are None

So instead of doing

if "location" in myDict.Keys():

You just do

if myDict["location"] is not None:

Solution 2:[2]

I have found an answer, based on @RJ Adriaansen solution, there it is (this will also check if argument is not self):

def clans(self, name: str = None, warFrequency: str = None, location: str = None,
                minMembers: int = None, maxMembers: int = None,
                minClanPoints: int = None, minClanLevel: int = None,
                labels: list[str] = None):
        params = {k: v for k, v in locals().items() if v is not None and v != self}
        #                                                            ^^^^^^^^^^^^^
        #                                                            small change
        return params

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2