Reputation: 647
Recently, I found ''.format
function very useful because it can improve readability a lot comparing to the %
formatting.
Trying to achieve simple string formatting:
data = {'year':2012, 'month':'april', 'location': 'q2dm1'}
year = 2012
month = 'april'
location = 'q2dm1'
a = "year: {year}, month: {month}, location: {location}"
print a.format(data)
print a.format(year=year, month=month, location=location)
print a.format(year, month, location)
Whilst two first prints do format as I expect (yes, something=something
looks ugly, but that's an example only), the last one would raise KeyError: 'year'
.
Is there any trick in python to create dictionary so it will automatically fill keys and values, for example somefunc(year, month, location)
will output {'year':year, 'month': month, 'location': location}
?
I'm pretty new to python and couldn't find any info on this topic, however a trick like this would improve and shrink my current code drastically.
Thanks in advance and pardon my English.
Upvotes: 5
Views: 20016
Reputation: 5448
As of Python 3.6, you can also use the new Formatted string literals (f-strings), which you can use with variables:
year = 2012
month = 'april'
location = 'q2dm1'
a = f"year: {year}, month: {month}, location: {location}"
print(a)
or a dictionary:
data = {'year': 2012, 'month': 'april', 'location': 'q2dm1'}
a = f"year: {data['year']}, month: {data['month']}, location: {data['location']}"
print(a)
Note the f
prefix before the string literal.
PEP 498: Formatted string literals:
Formatted string literals are prefixed with 'f' and are similar to the format strings accepted by str.format(). They contain replacement fields surrounded by curly braces. The replacement fields are expressions, which are evaluated at run time, and then formatted using the format() protocol:
>>> >>> name = "Fred" >>> f"He said his name is {name}." 'He said his name is Fred.' >>> width = 10 >>> precision = 4 >>> value = decimal.Decimal("12.34567") >>> f"result: {value:{width}.{precision}}" # nested fields 'result: 12.35'
...
Upvotes: 0
Reputation: 169693
data = {'year':2012, 'month':'april', 'location': 'q2dm1'}
a = "year: {year}, month: {month}, location: {location}"
print a.format(**data)
..is what you are looking for. It's functionally identical to doing .format(year=data['year'], ...)
, or the other examples you gave.
The double-asterix thing is a hard thing to search for, so it's usually referred to as "kwargs". Here's a good SO question on this syntax
Upvotes: 3
Reputation: 49886
You could pass locals()
:
a.format(**locals())
Of course, this has issues: you will have to pass everything in locals, and it can be difficult to understand the effect of renaming or removing a variable.
A better way would be:
a.format(**{k:v for k,v in locals() if k in ('year', 'month')})
# or; note that if you move the lambda expression elsewhere, you will get a different result
a.format(**(lambda ld = locals(): {k:ld[k] for k in ('year', 'month')})())
But this is not any more concise, unless you wrap it up with a function (which must of course take a dict parameter).
Upvotes: 1
Reputation: 318778
You can use the dict()
callable:
dict(year=yeah, month=month, location=location)
When passing keyword arguments it creates a dict containing the elements you specified as kwargs.
If you do not want to specify the argument names, use the positional style of .format()
:
>>> a = 'year {0} month {1} location {2}'
>>> print a.format(2012, 'april', 'abcd')
year 2012 month april location abcd
However, if you try to do something similar to what compact()
in PHP does (create a dict mapping variable names to its values without specifying name and variable separately), please don't. It just results in ugly unreadable code and would require nasty hacks anyway.
Upvotes: 1
Reputation: 23871
The first print
should be
print a.format(**data)
Also, if you are finding some shortcuts, you could write one like, no big difference.
def trans(year, month, location):
return dict(year=year, month=month, location=location)
Upvotes: 6