简体   繁体   中英

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.

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'}

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM