python's ".format" function - python

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.

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)

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

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.

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).

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

Related

What does format() in Python actually do?

I'm coming into Python3 after spending time with Ruby, R, and some Java. Immediately I've come across the format() function and I'm a little lost as to what it does. I've read Python | format() function and see that it somehow resembles this in ruby:
my_name = "Melanie"
puts "My name is #{my_name}."
Outputs:
"My name is Melanie."
However, I don't understand why I can't just use a variable as above. I must be very much misunderstanding the usage of the format() function. (I'm a novice, please be gentle.)
So what does format() actually do?
You can definitely use a variable in the string example that you have shown, in the following manner:
my_name = "Melanie"
Output = "My name is " + my_name + "."
print(Output)
My name is Melanie.
This is the easy way, but not the most elegant.
In the above example, I have used 3 lines and created 2 variables (my_name and Output)
However, I can get the same output using just one line of code and without creating any variables, using format()
print("My name is {}.".format("Melanie"))
My name is Melanie.
Curly braces {} are used as placeholders, and the value we wish to put in the placeholders are passed as parameters into the format function.
If you have more than one placeholder in the string, python will replace the placeholders by values, in order.
Just make sure that the number of values passed as parameters to format(), is equal to the number of placeholders created in the string.
For example:
print("My name is {}, and I am {}.".format("Melanie",26))
My name is Melanie, and I am 26.
There are 3 different ways to specify placeholders and their values:
Type 1:
print("My name is {name}, and I am {age}.".format(name="Melanie", age=26))
Type 2:
print("My name is {0}, and I am {1}.".format("Melanie",26))
Type 3:
print("My name is {}, and I am {}.".format("Melanie",26))
Additionally, by using format() instead of a variable, you can:
Specify the data type, and
Add a formatting type to format the result.
For example:
print("{0:^7} has completed {1:.3f} percent of task {2}".format("Melanie",75.765367,1))
Melanie has completed 75.765 percent of task 1.
I have set the data type for the percentage field to be a float, with 3 decimals, and given a character length of 7 to the name, and center-aligned it.
The alignment codes are:
' < ' :left-align text
' ^ ' :center text
' > ' :right-align
The format() method is helpful when you have multiple substitutions and formattings to perform on a string.
The format function is a method for string in python, it is use to add a variable to string. for example:
greetings = 'hello {0}'
visitor = input('please enter your name')
print(greetings.format(visitor))
it can also be use to pad/position string also, thisn actually align the visitor into to the greetings in 10 byte of space
greetings = 'hello {0:^10}'
visitor = input('please enter your name')
print(greetings.format(visitor))
Also, there are two type of format in python 3x: the format expression and the format function.
the format expression is actually this '%'
and many more on 'format'. Maybe you should check on the doc 'format' by typing "help(''.format)"
An example using the format function is this:
name = Arnold
age = 5
print("{ }, { }".format(name, age))
This displays:
Arnold, 5

Python - Formatting items in a list of numbers to be strings with currency symbol

I have a list of numbers that are currency values that I would like to convert to currencies with symbol:
Current list
list = [200,4002,4555,7533]
Given below is what is returned if I print the above list:
[(Decimal('200'), Decimal('4002'), Decimal('4555'), Decimal('7533')]
Expected output
list = ['$200','$4,002','$4,555','$7,533'] <<--These are basically number formatted for 1000's separator with the currency symbol
Assuming you want the output as strings:
In [123]: lst = [200,4002,4555,7533]
In [124]: [f'${cur:,}' for cur in lst]
Out[124]: ['$200', '$4,002', '$4,555', '$7,533']
Also don't name your variables as some built-in.
Avoid using builtin names like list for variables. You also can't output in this format without converting to strings, like below:
l = [200, 4002, 4555, 7533]
l = ['${:0,.0f}'.format(x) for x in l]
print(l)
Prints:
['$200', '$4,002', '$4,555', '$7,533']
Instead of manually formatting the values in your list to strings containing currency representations, it's a good idea to use standard library functions that are dedicated to exactly this job. Here, what you may want to use are the functions from the locale module. These functions provide a convenient way for instance to represent dates, times, and currencies in a format that is appropriate for the current locale settings. The locale can be either set by the operating system of the computer the program runs on, or by the programmer of the program itself.
The first thing you have to do is load the locale module. Then you set up the locale setting, either to the system default:
import locale
locale.setlocale(locale.LC_ALL, "") # to use the system-wide locale setting
or to a locale of your own choosing:
import locale
locale.setlocale(locale.LC_ALL, "en_US.utf-8") # to use the USA locale
Now, you can use the currency function to format a value using the current locale setting:
lst = [200, 4002, 4555, 7533]
cur_lst = [locale.currency(val) for val in lst]
print(cur_list)
['$200.00', '$4002.00', '$4555.00', '$7533.00']
The currency function has three options that allow you to tweak the output. The grouping option will insert appropriate grouping marks to separate thousands, millions etc.:
locale.currency(123456, grouping=True)
'$123,456.00'
locale.currency(123456, grouping=False) # the default
'$123456.00'
The international option uses the international standard currency abbreviation instead of the currency symbol:
locale.currency(123456, international=True)
'USD 123456.00'
locale.currency(123456, international=False) # the default
'$123456.00'
Lastly, setting the symbol option to True suppresses showing the currency symbol altogether.

Formatting of title in Matplotlib

I have the following python code:
def plot_only_rel():
filenames = find_csv_filenames(path)
for name in filenames:
sep_names = name.split('_')
Name = 'Name='+sep_names[0]
Test = 'Test='+sep_names[2]
Date = 'Date='+str(sep_names[5])+' '+str(sep_names[4])+' '+str(sep_names[3])
plt.figure()
plt.plot(atb_mat_2)
plt.title((Name, Test, Date))
However when I print the title on my figure it comes up in the format
(u'Name=X', u'Test=Ground', 'Date = 8 3 2012')
I have the questions:
Why do I get the 'u'? Howdo I get rid of it along with the brackets and quotation marks?
This also happens when I use suptitle.
Thanks for any help.
plt.title receives a string as it's argument, and you passed in a tuple (Name, Test, Date). Since it expects a string it tried to transform it to string using the tuple's __str__ method which gave you got output you got. You probably want to do something like:
plat.title('{0} {1}, {2}'.format(Name, Test, Date))
How about:
plt.title(', '.join(Name,Test,Date))
Since you are supplying the title as an array, it shows the representation of the array (Tuple actually).
The u tells you that it is an unicode string.
You could also use format to specify the format even better:
plt.title('{0}, {1}, {2}'.format(Name, Test, Date))
In Python > 3.6 you may even use f-string for easier formatting:
plt.title(f'{Name}, {Test}, {Date}')
I'd like to add to #Gustave Coste's answer: You can also use lists directly in f-strings
s="Santa_Claus_24_12_2021".split("_")
print(f'Name={s[0]}, Test={s[1]}, Date={s[2]} {s[3]} {s[4]}')
result: Name=Santa, Test=Claus, Date=24 12 2021. Or for your case:
plt.title(f'Name={sep_names[0]}, Test={sep_names[2]}, Date={sep_names[5]} {sep_names[4]} {sep_names[3]}')

SyntaxError: keyword can't be an expression while creating a dictionary

I got two strings retrieved from a cookie
name = 'rack.session'
val = 'CookieVal'
Using them I would like to build a dictionary
cookies = dict(rack.session=val)
but SyntaxError: keyword can't be an expression
So I tried to escape the (.) dot
re.escape(name)
... but it raises the same error
How is this possible? According to Python type() name is a string:
type(name)
<class 'str'>
Why is Python mixing up strings and expressions?
The problem with rack.session is that python thinks that you're trying to use the value of expression rack.session and pass it to dict(), which is incorrect because dict() expects you to pass variables names when you're using keyword arguments, these variables name are then converted to strings when the dict is created.
Simple example:
>>> dict('val' = 'a')
File "<ipython-input-21-1cdf9688c191>", line 1
SyntaxError: keyword can't be an expression
So, you can't use an object on the left side of =, you can only use a valid identifier.
Byte code makes it even more clear what happens with rack.session:
>>> import dis
>>> dis.dis(lambda : dict(rack.session , val))
1 0 LOAD_GLOBAL 0 (dict)
3 LOAD_GLOBAL 1 (rack) # load the object `rack`
6 LOAD_ATTR 2 (session)# use the value of it's attribute
# `session`
9 LOAD_GLOBAL 3 (val)
12 CALL_FUNCTION 2
15 RETURN_VALUE
So, with rack.session = val, python will think that you're trying to use the value returned from rack.session and pass it to dict, which is incorrect. Secondly rack.session isn't a valid identifier as dots(.) are not allowed in python identifiers.
This is applicable to any function in python not even dict, a keyword argument must be a valid identifier.
From the docs:
keyword_item ::= identifier "=" expression
Valid examples:
>>> dict(foo = 1, bar = '2')
{'foo': 1, 'bar': '2'}
For your example you can simply do:
>>> val = 'CookieVal'
>>> name = 'rack.session'
>>> dict(((name,val),))
{'rack.session': 'CookieVal'}
#or
>>> {name:val}
{'rack.session': 'CookieVal'}
>>> name = 'rack.session'
>>> val = 'CookieVal'
>>> cookies = {name: val}
>>> cookies
{'rack.session': 'CookieVal'}
name = 'rack.session'
val = 'CookieVal'
cookies = dict([(name,val)])
morecookies = {name:val}
As to "Why is Python mixing up strings and expressions?", it's not. I'm not sure why you think python is doing this. You are mixing up strings and variables, which are quite different.
You should build a dictionary this way
name = 'rack.session'
val = 'CookieVal'
d = {name: val}
print d
gives you
>>>
{'rack.session': 'CookieVal'}
>>>
More on dictionaries http://docs.python.org/2/tutorial/datastructures.html#dictionaries
The reason is that you give the dict this expression: rack.session=val, rather than a keyword.
Instead, you can get around this issue using dict({name: val}), where the argument is {name:val}. Of course, you could just use {name: val}.
The python docs shows several ways to create dicts.
The answer from Ashwini Chaudhary was quite good, but I can add more to clarify question.
The main reason why you've got this error is because your expression contain a point - '.' symbol. And raising error directly say that: "keyword can't be an expression".
This - '.' symbol makes Python think, that current keyword name is not a valid name, but an expression, that you try to evaluate. Generally speaking you may pass as a key in dict() only valid name, from the point that such names could be a names for a variables dispite the fact that no variable evaluation actually can be happen here.
So your keys must contain only alphabeticals, digits, or underscore, and do not start with a digit (they must be valid Python identifiers as was said before).
For example these are not valid:
d = dict(1='Bob')
d = dict(b.a='Bob')
d = dict('b'='Bob')
d = dict(b$='Bob')
First, second and third are not valid, because they are expressions and because they are not valid identifiers, but fourth only because it is not a valid identifier.
To circumvent current limitations you may use one of the ways that was mentioned above, cause they accepting variable evaluation and if the key is the string, it can contain any characters:
d = dict([(1, 'Bob')])
d = dict(zip([1],['Bob']))
d = {1:'bob'}
or this one:
d = dict.fromkeys([1])
d[1] = 'Bob'
And for example of key value evaluation difference:
x = 1
d = dict(x='Bob')
d
{'x': 'Bob'}
x = 1
d = dict([(x, 'Bob')])
d
{1: 'Bob'}
Try this:
name = 'rack.session'
val = 'CookieVal'
cookies = dict(zip([name],[val]))
Edit: my case is too much for your case
cookies = {name:val}
is enough

Use a string to call function in Python [duplicate]

This question already has answers here:
Calling a function of a module by using its name (a string)
(18 answers)
Closed 9 years ago.
Some days ago I was searching on the net and I found an interesting article about python dictionaries. It was about using the keys in the dictionary to call a function. In that article the author has defined some functions, and then a dictionary with key exactly same as the function name. Then he could get an input parameter from user and call the same method (something like implementing case break)
After that I realised about the same thing but somehow different. I want to know how I can implement this.
If I have a function:
def fullName( name = "noName", family = "noFamily" ):
return name += family
And now if I have a string like this:
myString = "fullName( name = 'Joe', family = 'Brand' )"
Is there a way to execute this query and get a result: JoeBrand
For example something I remember is that we might give a string to exec() statement and it does it for us. But I’m not sure about this special case, and also I do not know the efficient way in Python. And also I will be so grateful to help me how to handle that functions return value, for example in my case how can I print the full name returned by that function?
This does not exactly answer your question, but maybe it helps nevertheless:
As mentioned, eval should be avoided if possible. A better way imo is to use dictionary unpacking. This is also very dynamic and less error prone.
Example:
def fullName(name = "noName", family = "noFamily"):
return name + family
functionList = {'fullName': fullName}
function = 'fullName'
parameters = {'name': 'Foo', 'family': 'Bar'}
print functionList[function](**parameters)
# prints FooBar
parameters = {'name': 'Foo'}
print functionList[function](**parameters)
# prints FoonoFamily
You could use eval():
myString = "fullName( name = 'Joe', family = 'Brand' )"
result = eval(myString)
Beware though, eval() is considered evil by many people.
I know this question is rather old, but you could do something like this:
argsdict = {'name': 'Joe', 'family': 'Brand'}
globals()['fullName'](**argsdict)
argsdict is a dictionary of argument, globals calls the function using a string, and ** expands the dictionary to a parameter list. Much cleaner than eval. The only trouble lies in splitting up the string. A (very messy) solution:
example = 'fullName(name=\'Joe\',family=\'Brand\')'
# Split at left parenthesis
funcname, argsstr = example.split('(')
# Split the parameters
argsindex = argsstr.split(',')
# Create an empty dictionary
argsdict = dict()
# Remove the closing parenthesis
# Could probably be done better with re...
argsindex[-1] = argsindex[-1].replace(')', '')
for item in argsindex:
# Separate the parameter name and value
argname, argvalue = item.split('=')
# Add it to the dictionary
argsdict.update({argname: argvalue})
# Call our function
globals()[funcname](**argsdict)

Categories