30
loading...
This website collects cookies to deliver better user experience
f
before the string literal, like so:string = f'this is an f-string'
>>> name, birth_year = 'Tushar', 2000
>>> print(f'I am {name}, and I was born in {birth_year}')
I am Tushar, and I was born in 2000
>>> import datetime; now = datetime.datetime.now()
>>> print(f'I am {now.year - birth_year} years old')
I am 21 years old
>>> age = now.year - birth_year
>>> print(f'I am {"an adult" if age >= 18 else "a child"}.')
I am an adult.
>>>
%
sign has existed in Python ever since version 1.x (and even before that in C, which is where this feature's inspiration comes from). It allowed you to do most string formatting very easily, even though the syntax was a bit unusual: it uses %
flags in your string, which get replaced by the values you pass in. Here's an example:>>> city = 'London'
>>> print('She lives in %s since %d' % (city, 2000))
She lives in London since 2000
>>>
%
patterns, and each of them has a meaning:%s
- String%c
- Character (ASCII/Unicode)%d
- Digits (Integer)%f
- Floats%x
- Hexadecimal number, etc.%9s
means a string of length 9.%-7d
means an integer of length 7, but left-aligned.
>>> print('%15f seconds' % 31.415926)
31.415926 seconds
>>> print('%-15f seconds' % 31.415926)
31.415926 seconds
>>>
%
syntax borrowed from C might not be the most readable way to format strings. So in Python 3.0 (alongside 2.6), A new method was added to the str
data type: str.format
. Not only was it more obvious in what it was doing, it added a bunch of new features, like dynamic data types, center alignment, index-based formatting, and specifying padding characters. Here's a few examples:>>> month = 'May'
>>> print('I was born in {}.'.format(month))
I was born in May
>>> blog_title = 'What the f-string?'
>>> print('{title:-^30}'.format(title=blog_title))
------What the f-string?------
>>> print('{:_<15f} seconds'.format(31.415926))
31.415926______ seconds
>>> print('{:>15f} seconds'.format(31.415926))
31.415926 seconds
Note that if you don't specify an alignment character using <
, >
or ^
, it will always default to left alignment. This is different from %
-formatting, as that defaults to right-alignment for numbers.
str.format
method, there's also a built-in format
function which does the same thing.For a lot more information about %
-formatting and str.format
, and all of their (many) features, head to pyformat.info. It is very useful as a reference for the features and syntax.
str.format()
can already do (almost) everything that f-strings can do. You might be wondering then, "why were f-strings created in the firt place? And why should I care about them?">>> name, age = 'Mark', 31
>>> # str.format version
>>> print('Hi, I'm {0} and I'm {1} years old.'.format(name, age)
Hi, I'm Mark and I'm 31 years old.
>>> # f-string version
>>> print(f'Hi, I'm {name} and I'm {age} years old.')
Hi, I'm Mark and I'm 31 years old.
>>> pi = 3.141592
>>> print(f'{pi}')
3.141592
>>> print(f'{pi:10}') # padding to make length 10
3.141592
>>> print(f'{pi:010}') # padding with zeroes
003.141592
>>> print(f'{pi:.3}') # 3 digits total, ignoring decimal
3.14
>>> string = "Hello! this is a string"
>>> print(f'{string:.6}') # 6 characters
'Hello!'
>>> heading = 'Test'
>>> print(f'{heading:>20}')
Test
>>> print(f'{heading:~>20}') # specify alignment for custom padding
~~~~~~~~~~~~~~~~Test
>>> print(f'{heading:_<20}')
Test________________
>>> print(f'{heading:=^20}')
========Test========
>>>
>>> num = 2.136
>>> print(f'{num}')
2.136
>>> print(f'{num:.3}') # Rounded up
2.14
>>> print(f'{num:.2}') # Rounded down
2.1
>>>
>>> print(f'{42:c}') # int to ascii
*
>>> print(f'{604:f}') # int to float
604.000000
>>> print(f'{84:.2f}%')
84.00%
>>> print(f'{604:x}') # int to hex
25c
>>> print(f'{604:b}') # int to binary
1001011100
>>> print(f'{604:0>16b}') # int to binary, with zero-padding
0000001001011100
>>>
>>> large_num = 12_345_678 # int syntax supports underscores :D
>>> print(f'{large_num}')
12345678
>>> print(f'{large_num:,}')
12,345,678
%
-formatting:>>> from datetime import datetime
>>> datetime.now() # repr value
datetime.datetime(2021, 7, 6, 2, 21, 56, 698285)
>>> print(datetime.now()) # str value
2021-07-06 02:22:02.772826
>>> print(f'{datetime.now()}') # str value by default
2021-07-06 02:22:14.357562
>>> print(f'{datetime.now()!r}') # repr value
datetime.datetime(2021, 7, 6, 2, 22, 17, 709937)
>>> print(f'{datetime.now()!s}') # str value
2021-07-06 02:22:20.081837
>>> sparkles = '✨'
>>> print(f'{sparkles}')
✨
>>> print(f'{sparkles!a}') # ascii-safe value
'\u2728'
>>> from datetime import datetime
>>> print(f'{datetime.now():%A, %B %d %Y}')
Tuesday, July 06 2021
For more info on the %
codes specifically for datetime objects, check out the documentation for datetime.strftime
, or check out strftime.org.
f'{abc=}'
is the same as f'abc={abc!r}'
.>>> x, y = 3, 5
>>> print(f'{x=}')
x=3
>>> print(f'{x = }')
x = 3
>>> x, y = y, x+y
>>> print(f'{x=} {y=}')
x=5 y=8
>>> string = 'test'.center(10, '*')
>>> print(f'{string = }')
string = '***test***'
>>> print(f'{10 * 2 = }')
10 * 2 = 20
>>>
~^30s
or 0>12,.2f
, it makes sense to be able to extract those out into variables as well. And that's exactly what nested formatting lets us do.>>> string = 'Python'
>>> size = 20
>>> print(f'{string:{size}}')
~~~~~~~Python~~~~~~~
>>>
from math import pi
digits = int(input('Enter number of digits of pi: '))
length = int(input('Enter string length: '))
alignment = input('Enter alignment (<, > or ^): ')
padding_char = input('Enter padding character: ')
print(f'{pi:{padding_char}{alignment}{length}.{digits}}')
Enter number of digits of pi: 8
Enter string length: 30
Enter alignment (<, > or ^): ^
Enter padding character: _
__________3.1415927___________
__format__
method on the formatter object. This allows you to define (mostly) arbitrary formatting semantics.from datetime import datetime
class BetterDatetime(datetime):
substitutions = {
'%day': '%A',
'%date': '%d',
'%monthname': '%B',
'%month': '%m',
'%year': '%Y'
}
def __format__(self, format_spec):
for token, replacement in self.substitutions.items():
format_spec = format_spec.replace(token, replacement)
return super().__format__(format_spec)
print(f'Today is {BetterDatetime.now():%day, %date %monthname %year}')
# Output: Today is Monday, 8 July 2021
You can't separate the string template from the data being embedded. In str.format, you can store the strings themselves as templates in a separate file, like text = '{user} has left'
. Then, you can import text
and use text.format(user=...)
. You can't do this with f-strings.
f-strings only work in Python 3.6+, and {x=}
syntax only works in Python 3.8+
There's also no real replacement for the str.format_map
method using f-strings.