Phellipe Brasiliano
Phellipe Brasiliano

Reputation: 37

How to create objects with a list of optional elements from a dictionary?

I've been learning how to program and this is problem I'm having trouble solving:

I have a class User that takes 4 parameters, 2 required and 2 optional:

class User:
    def __init__(self, user_id, first_name, last_name='', username=''):
        self.user_id = user_id
        self.first_name = first_name
        self.last_name = last_name
        self.username = username

then I make a function to create those objects, they take a dictionary and use looks in the keys to create the objects

users={}


def user_register(user_info):
if user_info['id'] in users:
    pass
else:
    print('cadastrando...')
    users[user_info['id']] = User(user_info['id'], user_info['first_name'],
                                  user_info['last_name'], user_info['username'])

example_userinfo1 = {'id':111, 'first_name':'john', 'last_name':'smith', 'username':'@johnsmith'}

example_userinfo2 = {'id':222, 'first_name':'bob'}

so like this it only works if the dictionary given has all the four keys,which is the case of example_userinfo1, but not the case for example_userinfo2 (only ID and first_name are mandatory). I would like to know what is the way of checking if the key exists before passing it as an argument, I tried something like this with no success:

User(user_info['id'], user_info['first_name'],
        if 'last_name' in user_info: last_name=user_info['last_name'],
        if 'username' in user_info: username=user_info['username'])

so what is a good way to overcome this problem? also I would like to know if there are many signs of bad practices on my code (as I am trying to start paying attention to those things)

Upvotes: 0

Views: 364

Answers (2)

Moinuddin Quadri
Moinuddin Quadri

Reputation: 48100

Better way to do this is to unpack the dict using **. For example:

>>> userinfo = {'user_id':222, 'first_name':'bob'}
#                  ^  I am using `user_id` instead of `id`. 
#                     Continue reading for explanation
>>> User(**userinfo)
<__main__.User instance at 0x7f1f4c70cf80>

When you unpack the dict within the function call, it maps the dict key with the function parameters and the dict value as the value of parameter. So in this case, your function call was like:

User(user_id=222, first_name='bob')

Edit: Based on additional information from user as id is returned from API. And it is not good to use id as variable since id() is built-in function in python. In this case, you can modify dict explicitly as:

>>> userinfo = {'id':222, 'first_name':'bob'}
>>> userinfo['user_id'] = userinfo['id']
>>> del userinfo['id']
>>> userinfo
{'first_name': 'bob', 'user_id': 222}   # Final value hold by dict

Upvotes: 1

Martijn Pieters
Martijn Pieters

Reputation: 1124070

Make your dictionary keys correspond dir to the argument names, just apply the whole dictionary as keyword arguments:

user_id = user_info.pop('id')
users[user_id]  = User(user_id, **user_info)

I used dict.pop() to remove the 'id' key as your class expects user_id instead. You already supplied default values for any missing keys.

Otherwise, you could have used dict.get() to return an empty string if a key is missing:

User(user_info['id'], user_info['first_name'],
    last_name=user_info.get('last_name', ''),
    username=user_info.get('username', ''))

Upvotes: 1

Related Questions