Reputation: 4132
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?
Upvotes: 60
Views: 51771
Reputation: 1213
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.
Upvotes: 1
Reputation: 2768
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}
Upvotes: 27
Reputation: 6090
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
Upvotes: 1
Reputation: 31
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
.
Upvotes: 3
Reputation: 49187
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')))
Upvotes: 32
Reputation: 993025
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.
Upvotes: 2
Reputation: 90742
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.
Upvotes: 8
Reputation: 212845
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.
Upvotes: -4