Create dictionary from list of variables

Question:

I’m looking for a way to create a dictionary without writing the key explicitly.
I want to create a function that gets the number of variables and creates a dictionary where the variable names are the keys and their values are the variable values.

Instead of writing the following function:

def foo():
    first_name = "daniel"
    second_name = "daniel"
    id = 1
    return {'first_name':first_name, 'second_name':second_name}

I want to get the same result with function :

create_dict_from_variables(first_name, second_name)

Is there any way to do so?

Asked By: Idok

||

Answers:

You cannot do this.

Your function could be defined as:

def create_dict_from_variables(first_name, second_name):
    return something_from(first_name, second_name)

and you can call this function:

create_dict_from_variables('abcd', 'efgh')

These two arguments 'abcd' and 'efgh' are not named variables.

Answered By: eumiro

You can use locals, but I would recommend against it. Do it explicitly.

>>> import this
[...]
Explicit is better than implicit.
[...]

Your code will generally be better, more predictable, less prone to breaking and more comprehensible if you do it explicitly.

Answered By: Chris Morgan

No, there isn’t, because Python functions don’t get information about the variables used to call the function. Also, imagine doing something like this:

create_dict_from_variables(first_name[:-3] + "moo", last_name[::2])

The function will have no way of knowing the expressions used to create the parameters.

Answered By: Greg Hewgill

You can’t do it without writing at least the variable names, but a shorthand can be written like this:

>>> foo = 1
>>> bar = 2
>>> d = dict(((k, eval(k)) for k in ('foo', 'bar')))
>>> d
{'foo': 1, 'bar': 2}

or as a function:

def createDict(*args):
     return dict(((k, eval(k)) for k in args))

>>> createDict('foo','bar')
{'foo': 1, 'bar': 2}

you can also use globals() instead of eval():

>>> dict(((k, globals()[k]) for k in ('foo', 'bar')))
Answered By: Not_a_Golfer

In principle this is possible by passing variable names to function create_dict and then reaching to a caller stack frame from within create_dict function using module inspect.

Answered By: Vasus

There is an interesting solution to this problem, which doesn’t involve external libraries. However, a slightly different syntax is needed: eval(f(a,b))

# Auxiliary Function
f = lambda s: f"dict({ ','.join( f'{k}={k}' for k in s.split(',') ) })"

first_name  = "daniel"
second_name = "joe"
D           = eval(f('first_name,second_name'))

print(D)
# {'first_name': 'daniel', 'second_name': 'joe'}

In the example above, the main goal of the OP is still accomplished, in the sense that we only type the names of the variables once to create a dictionary. However, the syntax is still a bit verbose.

PS. One important benefit of the code above is that we evaluate the dictionary in its original namespace, which removes any restrictions with respect to the scope of the function (globals(), locals(), etc.). This was my main motivation behind using this approach.

Answered By: C-3PO

In fact, there is a way:

from varname import nameof

def foo(first_name,second_name):
    return {nameof(first_name):first_name, nameof(second_name):second_name}

first_name = "daniel"
second_name = "daniel"

print (foo(first_name,second_name))

Output:

{'first_name': 'daniel', 'second_name': 'daniel'}

You can get the python-varname package below:

https://github.com/pwwang/python-varname

Basic use:

from varname import nameof

s = 'Hey!'

print (nameof(s))

Output:

s
Answered By: Synthase

pip install sorcery

from sorcery import dict_of

a = 1
b = 2
c = 3
d = dict_of(a, b, c)
print(d)
# {'a': 1, 'b': 2, 'c': 3}
Answered By: alexeydemin
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.