There are two (old one new) styles of string formatting in Python. They are very similar when dealing with simple stuff but also have a lot of in-deep presentation and text transformation options
printf-style (%, old) - based on C printf style formatting that handles a narrower range of types and is slightly harder to use correctly, but is often faster for the cases it can handle.
str.format() (new) provides a large degree of flexibility and customization.
f-strings (Python 3.6) - inline formatting allowing to insert variables by names with format similar to format()
🪄 Code:
print_me =100500.12print( "1. %s"% print_me )# Old format, %print( "2. {}".format(print_me) )# New format, format()print( f"3. {print_me}" )# f-strings
📟 Output:
1. 100500.12
2. 100500.12
3. 100500.12
% (printf-style formatting)
format % values
format is a string, % conversion specifications in format are replaced with zero or more elements of values.
A conversion specifier contains two or more characters and has the following components, which must occur in this order:
1. The '%' character - the start of the specifier.
2. Mapping key (optional), key name in parentheses (for example: (somename)).
3. Conversion flags (optional), which affect the result of some conversion types.
4. Minimum field width (optional). If specified as an '*' (asterisk), the actual width is read from the next element of the tuple in values, and the object to convert comes after the minimum field width and optional precision.
5. Precision (optional), given as a '.' (dot) followed by the precision. If specified as '*' (an asterisk), the actual precision is read from the next element of the tuple in values, and the value to convert comes after the precision.
6. Length modifier (optional).
7. Conversion type.
🪄 Code:
food ="Ceasar salad"print("For breakfast today is %s"% food)
📟 Output:
For breakfast today is Ceasar salad
🪄 Code:
food ="Pizza Pepperoni and burger"money =130.23print( "For lunch we have: %35s, budget: %012.3f UAH"% (food, money) )
📟 Output:
For lunch we have: Pizza Pepperoni and burger, budget: 00000130.230 UAH
🪄 Code:
data ={"food":"Pasta Carbonara","money":300}print( "And for dinner: %(food)20s, money to spend: %(money)9.2f UAH"% data )
📟 Output:
And for dinner: Pasta Carbonara, money to spend: 300.00 UAH
{} / format()
It's better to use this for something that requries more complex formatting
Format strings contain “replacement fields” surrounded by curly braces {}. Anything that is not contained in braces is considered literal text, which is copied unchanged to the output. If you need to include a brace character in the literal text, it can be escaped by doubling: {{ and }}.
Food: 'Pizza Pepperoni and burger', money: 130.23 UAH
It is possible when using new format (format()) to specify positions:
🪄 Code:
print("Food is {1}, money: {0}, (I have exactly ${0} in my wallet!)".format(money, food))
📟 Output:
Food is Pizza Pepperoni and burger, money: 130.23, (I have exactly $130.23 in my wallet!)
It is possible to pass arguments by names:
data ={"money":45,"food":"salad"}# `**` - means we are passing dict as a sequence of key-value pairsprint("Want {food} but ${money} to spend".format(**data))# print("Want {food} but ${money} to spend".format(money=45, food="salad"))
📟 Output:
Want salad but $45 to spend
More examples:
🪄 Code:
"First thing in the morning is {0}".format("coffee")# References first positional argument
📟 Output:
'First thing in the morning is coffee'
🪄 Code:
"I'd like a {} with coffee".format("cookie")# Implicitly references the first positional argument
📟 Output:
"I'd like a cookie with coffee"
🪄 Code:
"Bring me {} and {}".format("coffee", "cookie")# Same as "From {0} to {1}"
📟 Output:
'Bring me coffee and cookie'
🪄 Code:
"Remember my name: {name}".format(name="Heisenberg")# References keyword argument 'name'
📟 Output:
'Remember my name: Heisenberg'
🪄 Code:
data =dict(do_what="Remember", my_what="name", name="Heisenberg")"{do_what} my {my_what}: {name}".format(**data)
📟 Output:
'Remember my name: Heisenberg'
🪄 Code:
"String has this method: {0.isalpha}".format("")# 'isalpha' attribute of first positional arg
📟 Output:
'String has this method: <built-in method isalpha of str object at 0x7efc5848c030>'
Differences between formatters:
In last example assuming p is the instance of Plant class defined like:
classPlant(object):type='tree
.format() cheatsheet
.format() "cheats"
Show the same string several times
🪄 Code:
print('''{0}!{1}. "{0}!" {1}. "What's gone with that boy, I wonder? You {0}!" {1}. '''.format('TOM', 'No answer'))
📟 Output:
TOM!
No answer.
"TOM!"
No answer.
"What's gone with that boy, I wonder? You TOM!" No answer.
Convert Values to different Bases
You can use the following letters to convert a number to their bases:
New feature appeared in Python 3.6. It is possible to inject local variable right into string (variable interpolation)
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
var =34.125print(f'{var}')print(f'{var:012.3f}')print(f'{var:_^12.3f}')print(f'{var:^10}')
📟 Output:
34.125
00000034.125
___34.125___
34.125
In case interpolating var is not defined - you'll get regular NameError:
🪄 Code:
f'{unexistent_var}'
📟 Output:
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
Input In [372], in <cell line: 1>()
----> 1 f'{unexistent_var}'
NameError: name 'unexistent_var' is not defined
🪄 Code:
f'{1/0}'
📟 Output:
---------------------------------------------------------------------------
ZeroDivisionError Traceback (most recent call last)
Input In [373], in <cell line: 1>()
----> 1 f'{1/0}'
ZeroDivisionError: division by zero
f-string are evaluated only during creation (once):
🪄 Code:
value =100500str_ =f'Value is {value}'print(str_)
📟 Output:
Value is 100500
🪄 Code:
value =42print(str_)
📟 Output:
Value is 100500
Expressions may be evaluated directly inside a string:
🪄 Code:
f'{1+2}'
📟 Output:
'3'
🪄 Code:
f'{"just another string"}''quoted string'
📟 Output:
'quoted string'
🪄 Code:
d = {"a": 100500}
l = [1, 2, 3, 4, 5]
f'{d["a"], l[2:5]}'
📟 Output:
'(100500, [3, 4, 5])'
🪄 Code:
def foo(x):
return "Hello! %s" % x
print(f'Result of function is:\n{foo("John")}')
A bit underrated feature of builtin string module. Template is very simple template engine.
🪄 Code:
from string import Template
s = Template('$who likes $what')
print(s.substitute(who='Johnny', what='whiskey'))
d = dict(who='tim')
#Template('Give $who $cookie').substitute(d) <--- will raise KeyError as 'cookie' not in a dictionary
print(Template('$who likes $cookies').safe_substitute(d)) # proper way