piny
piny

Reputation: 153

Is there a more efficient way of storing keyword arguments?

So here is my code:

def formateUserData(FirstName = None, MiddleName = None, LastName = None, DOB = None, Gender = None):
    formatedUserData = {}
    dataFieldKeys = ['First Name', 'Middle Name', 'Last Name', 'DOB', 'Gender']
    dataFieldValues = [FirstName, MiddleName, LastName, DOB, Gender]

    for key, value in zip(dataFieldKeys, dataFieldValues):
        if value: formatedUserData[key] = value

    return formatedUserData

As you can see, the keyword arguments has to be repeated 3 times (first in line 1, second in line 3 and third in line 4). Is there a way I could do the same thing without by just storing the keyword arguments once? Maybe by using some way to iterate through the keyword arguments if that possible? BTW, I'm looking to not use **kwargs.

Upvotes: 0

Views: 96

Answers (2)

Glauco
Glauco

Reputation: 1465

For my point of view the shortest solution is to use locals():

def formateUserData2(FirstName = None, MiddleName = None, LastName = None, DOB = None, Gender = None):
    return {k:v for k,v in locals().items() if v}

But this solution don't consider the change of labels, so a binding is required

def formateUserData(FirstName = None, MiddleName = None, LastName = None, DOB = None, Gender = None):
    binding = {'First Name':FirstName, 
               'Middle Name':MiddleName,
               'Last Name':LastName,
               'DOB':DOB,
               'Gender':Gender}
    return {k:v for k,v in binding.items() if v}

Use an explicit binding is a good practice, because it clarify what is your expectation.

Upvotes: 0

Raphael
Raphael

Reputation: 1801

maybe this scratch inspires you to condsider dataclasses which I find very handy

from dataclasses import dataclass, fields
from datetime import date
from typing import Literal, Optional

@dataclass
class User:
    first_name: Optional[str] = None
    middle_name: Optional[str] = None
    last_name: Optional[str] = None
    dob: Optional[date] = None
    gender: Optional[Literal['male', 'female']] = None


def not_none_dict(user: User) -> dict:
    not_none = {}
    for field in fields(user):
        value = getattr(user, field.name)
        if value:
            not_none[field.name] = value
    return not_none

print(
    not_none_dict(User(
        first_name='Joe',
        last_name='Doe'
    ))
)
>>> {'first_name': 'Joe', 'last_name': 'Doe'}

Upvotes: 1

Related Questions