{
"cells": [
{
"cell_type": "markdown",
"id": "e8e28b87-258c-4e5f-ad23-3f58618e4cce",
"metadata": {},
"source": [
"Cheat sheets\n",
"
\n",
"# Python f-strings\n",
"\n",
"All currently supported Python versions (3.6+) support string-formatting via f-strings. While [PEP 498 (Literal String Interpolation)](https://peps.python.org/pep-0498/) as well as the Python documention ([tutorial](https://docs.python.org/3/tutorial/inputoutput.html#formatted-string-literals), [syntax reference](https://docs.python.org/3/reference/lexical_analysis.html#f-strings)) have some information on their usage, I was missing a reference which is terse, but still verbose enough to explain the syntax.\n",
"\n",
"Thus, fstring.help was born, made with
and
(initially as a quick hack at PyConDE 2022).\n",
"\n",
"Created by 
\n",
"[Trainings, coaching and development for pytest, Qt and other Python/development topics](https://bruhin.software/).\n",
"\n",
"Some content is copied verbatim from [pyformat.info](https://pyformat.info/) (Copyright 2015 Ulrich Petri, Horst Gutmann). Thanks!\n",
"\n",
"Cheat sheet tables can be found at [fstring.help/cheat](https://fstring.help/cheat) thanks to Trey Hunner.\n",
"\n",
"Repository on
Github, contributions welcome! If you prefer an interactive version, [](https://mybinder.org/v2/gh/The-Compiler/fstring.help/HEAD?labpath=en.ipynb).\n",
"\n",
"## Basic formatting\n",
"\n",
"f-strings are strings with an `f` in front of them: `f\"...\"` or `f'...'`. Inside the f-string, curly braces can be used to format values into it:"
]
},
{
"cell_type": "code",
"execution_count": 1,
"id": "5437fc80-7453-4ee3-b5cf-34fee55bcba7",
"metadata": {},
"outputs": [],
"source": [
"one = 1\n",
"two = 2"
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "6c12f58b-56ad-45de-8c67-40ffa57b9a14",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"'1, 2'"
]
},
"execution_count": 2,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"f\"{one}, {two}\""
]
},
{
"cell_type": "markdown",
"id": "70c52102-51b5-4b2e-9cb7-a647a722b8b3",
"metadata": {},
"source": [
"## Arbitrary code\n",
"\n",
"You can put any Python code into f-strings:"
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "32dc365a-8652-4d1a-bed8-ff86ceaeefb6",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"'1 + 2 = 3'"
]
},
"execution_count": 3,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"f\"{one} + {two} = {one + two}\""
]
},
{
"cell_type": "markdown",
"id": "1ad8c6a2-acac-41e0-b943-acf9afda01d5",
"metadata": {},
"source": [
"This can also be used to access dictionary entries:"
]
},
{
"cell_type": "code",
"execution_count": 4,
"id": "70511aea-5faa-459c-9789-3b2f1bd5b83c",
"metadata": {},
"outputs": [],
"source": [
"colors = {\n",
" \"red\": \"#ff0000\",\n",
" \"green\": \"#00ff00\",\n",
" \"blue\": \"#0000ff\",\n",
"}"
]
},
{
"cell_type": "code",
"execution_count": 5,
"id": "fa9e9ee5-af6d-4000-a339-000804ce90fe",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"'red: #ff0000'"
]
},
"execution_count": 5,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"f\"red: {colors['red']}\""
]
},
{
"cell_type": "markdown",
"id": "eb4abc6c-a285-4eb2-bc19-b9babdaced56",
"metadata": {},
"source": [
"Similarly, you can access list items:"
]
},
{
"cell_type": "code",
"execution_count": 6,
"id": "33bb3e29-4e2c-4b69-b1f1-85116649cdc7",
"metadata": {},
"outputs": [],
"source": [
"data = [4, 8, 15, 16, 23, 42]"
]
},
{
"cell_type": "code",
"execution_count": 7,
"id": "f870b3e3-854a-4844-8159-40795ef8616a",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"'Best numbers: 23 and 42'"
]
},
"execution_count": 7,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"f\"Best numbers: {data[4]} and {data[5]}\""
]
},
{
"cell_type": "markdown",
"id": "8c9a9bd1-fe89-4537-8e52-0d0d11933e33",
"metadata": {},
"source": [
"Or attributes:"
]
},
{
"cell_type": "code",
"execution_count": 8,
"id": "98b97d2b-fa0d-46b7-b14d-4829aadd3cc2",
"metadata": {},
"outputs": [],
"source": [
"from dataclasses import dataclass\n",
"\n",
"@dataclass\n",
"class Point:\n",
" \n",
" x: int\n",
" y: int\n",
" \n",
"pos = Point(23, 42)"
]
},
{
"cell_type": "code",
"execution_count": 9,
"id": "b1c21a88-20c6-41f5-b2f7-16a4e2520339",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"'23, 42'"
]
},
"execution_count": 9,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"f\"{pos.x}, {pos.y}\""
]
},
{
"cell_type": "markdown",
"id": "dc8456f1-33fd-444a-a602-ca410f44ddfd",
"metadata": {},
"source": [
"Or even call functions:"
]
},
{
"cell_type": "code",
"execution_count": 10,
"id": "ab980683-597c-48bc-a46e-bd35667b6bec",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"'bigger value: 42'"
]
},
"execution_count": 10,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"f\"bigger value: {max(pos.x, pos.y)}\""
]
},
{
"cell_type": "markdown",
"id": "2a6ecc00-06d2-4c78-b691-062b39bd373e",
"metadata": {},
"source": [
"Note, however, that this should be used with care: Complex expressions are better first assigned to a variable.\n",
"\n",
"## Using f-strings for debugging\n",
"### Debug expressions\n",
"\n",
"Python 3.8 [added support](https://docs.python.org/3/whatsnew/3.8.html#f-strings-support-for-self-documenting-expressions-and-debugging) for self-documenting expressions and debugging - some examples adapted from the \"what's new\" document:"
]
},
{
"cell_type": "code",
"execution_count": 11,
"id": "f6c5823c-078b-4d70-9427-57efbad36def",
"metadata": {},
"outputs": [],
"source": [
"from datetime import date\n",
"user = \"eric_idle\"\n",
"member_since = date(1975, 7, 31)\n",
"delta = date(2022, 4, 11) - member_since"
]
},
{
"cell_type": "code",
"execution_count": 12,
"id": "f13f2f0e-f7a4-47a8-9665-33a2df7eba85",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"\"user='eric_idle' member_since=datetime.date(1975, 7, 31)\""
]
},
"execution_count": 12,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"f\"{user=} {member_since=}\""
]
},
{
"cell_type": "markdown",
"id": "36b13eee-dd74-49fd-8f0a-cb41799e28f2",
"metadata": {},
"source": [
"The usual f-string format specifiers (see below) allow more control over how the result of the expression is displayed:"
]
},
{
"cell_type": "code",
"execution_count": 13,
"id": "4de2c685-5256-49d1-ac88-b749baa747ff",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"'user=eric_idle delta.days=17,056'"
]
},
"execution_count": 13,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"f\"{user=!s} {delta.days=:,d}\""
]
},
{
"cell_type": "markdown",
"id": "348816a0-b48d-47c2-8373-e29c50339901",
"metadata": {},
"source": [
"Whitespace around the `=` is preserved in the output:"
]
},
{
"cell_type": "code",
"execution_count": 14,
"id": "ead37396-af53-4d77-a035-c8967d79aa80",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"\"user = 'eric_idle'\""
]
},
"execution_count": 14,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"f\"{user = }\""
]
},
{
"cell_type": "markdown",
"id": "e737878f-bdb5-4eff-900d-565071a92994",
"metadata": {},
"source": [
"The whole expression is displayed, so that calculations can be shown:"
]
},
{
"cell_type": "code",
"execution_count": 15,
"id": "1e2e0e4a-58a7-42bb-aca2-016e723cf911",
"metadata": {},
"outputs": [],
"source": [
"from math import cos, radians\n",
"theta = 30"
]
},
{
"cell_type": "code",
"execution_count": 16,
"id": "088bc265-1de7-40c4-abb4-7e2266ab2263",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"'theta=30 cos(radians(theta))=0.866'"
]
},
"execution_count": 16,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"f\"{theta=} {cos(radians(theta))=:.3f}\""
]
},
{
"cell_type": "markdown",
"id": "8c5907cd-d3c5-40c2-bf9a-2f52f3ff9447",
"metadata": {},
"source": [
"### Printing debug representation (repr)"
]
},
{
"cell_type": "markdown",
"id": "d0329aaf-66e3-4ef5-b7f2-1cc325a0ba60",
"metadata": {},
"source": [
"Since f-strings support running any code, just call `repr(...)` on your object:"
]
},
{
"cell_type": "code",
"execution_count": 17,
"id": "ee5a4dab-74f3-4f3e-972d-fd83b3b14e2f",
"metadata": {},
"outputs": [],
"source": [
"class Data:\n",
" \n",
" def __repr__(self):\n",
" return ''\n",
" \n",
" def __str__(self):\n",
" return 'string representation'\n",
"\n",
" \n",
"data = Data()"
]
},
{
"cell_type": "code",
"execution_count": 18,
"id": "d1c52d54-ebb9-4b82-aa39-da5fbbe42363",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"'data: string representation'"
]
},
"execution_count": 18,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"f\"data: {data}\""
]
},
{
"cell_type": "code",
"execution_count": 19,
"id": "47da2424-2e05-4687-b3eb-02ad92892ab6",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"'data: '"
]
},
"execution_count": 19,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"f\"data: {repr(data)}\""
]
},
{
"cell_type": "markdown",
"id": "857e04ef-b0e1-4efd-9952-e043018eea0e",
"metadata": {},
"source": [
"Alternatively, use the `!r` suffix like with `.format()`:"
]
},
{
"cell_type": "code",
"execution_count": 20,
"id": "40a8870a-f18e-4447-abf4-05a041c54780",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"'data: '"
]
},
"execution_count": 20,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"f\"data: {data!r}\""
]
},
{
"cell_type": "markdown",
"id": "7451fba0-eb73-4ce8-9b12-2f2bf63b17e0",
"metadata": {},
"source": [
"An `!s` suffix to convert to a string explicitly is also supported, though often not needed (as this is the default behavior in most cases):"
]
},
{
"cell_type": "code",
"execution_count": 21,
"id": "92553415-2372-48db-9346-b03b94313c31",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"'data: string representation'"
]
},
"execution_count": 21,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"f\"data: {data!s}\""
]
},
{
"cell_type": "markdown",
"id": "dfc873a0-0047-40b9-85ac-2675f4a0b0d9",
"metadata": {},
"source": [
"## Padding, aligning and truncating\n",
"\n",
"### Padding/aligning strings\n",
"\n",
"By default, values are formatted to take up only as many characters as needed to represent the content. It is however also possible to define that a value should be padded to a specific length.\n",
"\n",
"Align right:"
]
},
{
"cell_type": "code",
"execution_count": 22,
"id": "fd3bfad7-cea7-47af-97a2-b899d0e31a90",
"metadata": {},
"outputs": [],
"source": [
"val = \"test\""
]
},
{
"cell_type": "code",
"execution_count": 23,
"id": "3f715905-d1f3-4a7f-bf70-17358b249257",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"' test'"
]
},
"execution_count": 23,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"f\"{val:>10}\""
]
},
{
"cell_type": "markdown",
"id": "00664888-43d3-4a75-a936-2e09951859dd",
"metadata": {},
"source": [
"Align left:"
]
},
{
"cell_type": "code",
"execution_count": 24,
"id": "cfa0df0e-4b06-42c4-ba98-fc65a43068c9",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"'test '"
]
},
"execution_count": 24,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"f\"{val:<10}\""
]
},
{
"cell_type": "markdown",
"id": "efbf7139-362c-4037-9b9d-d13be6609c81",
"metadata": {},
"source": [
"You are able to choose the padding character:"
]
},
{
"cell_type": "code",
"execution_count": 25,
"id": "5dcdaf90-257b-4228-a865-97ec66c8eeef",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"'test______'"
]
},
"execution_count": 25,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"f\"{val:_<10}\""
]
},
{
"cell_type": "markdown",
"id": "3daece74-840c-482b-8363-3a52870a640b",
"metadata": {},
"source": [
"And also center align values:\n",
"\n"
]
},
{
"cell_type": "code",
"execution_count": 26,
"id": "b7eadce0-2fa1-41a6-9dd1-a8844880791f",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"' test '"
]
},
"execution_count": 26,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"f\"{val:^10}\""
]
},
{
"cell_type": "markdown",
"id": "71727393-5750-4bb8-b310-bbe034a1daf8",
"metadata": {},
"source": [
"By default, strings are left-aligned:"
]
},
{
"cell_type": "code",
"execution_count": 27,
"id": "15238c82-99d7-4b63-afae-9b9bf6aeaf3d",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"'test '"
]
},
"execution_count": 27,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"f\"{val:10}\""
]
},
{
"cell_type": "markdown",
"id": "075b9807-4c58-4b36-b5c4-e571dc40daa5",
"metadata": {},
"source": [
"but numbers are right-aligned:"
]
},
{
"cell_type": "code",
"execution_count": 28,
"id": "e83b1927-0778-4931-aba1-5b78eb2ef4e0",
"metadata": {},
"outputs": [],
"source": [
"answer = 42"
]
},
{
"cell_type": "code",
"execution_count": 29,
"id": "f09e3865-454c-4d19-9230-e719daa2526d",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"' 42'"
]
},
"execution_count": 29,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"f\"{answer:10}\""
]
},
{
"cell_type": "markdown",
"id": "b85fc6e2-9a7b-4108-9774-2b2c29424120",
"metadata": {},
"source": [
"When using center alignment, where the length of the string leads to an uneven split of the padding characters, the extra character will be placed on the right side:"
]
},
{
"cell_type": "code",
"execution_count": 30,
"id": "b65d222f-07f3-4ed1-a7f2-e7069fae0558",
"metadata": {},
"outputs": [],
"source": [
"archive = 'zip'"
]
},
{
"cell_type": "code",
"execution_count": 31,
"id": "9d421e21-dfa4-4360-bf1e-3f930b97220c",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"' zip '"
]
},
"execution_count": 31,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"f\"{archive:^6}\""
]
},
{
"cell_type": "markdown",
"id": "d263cdfc-608f-4a71-930f-6cf03ae61fe9",
"metadata": {},
"source": [
"### Truncating long strings"
]
},
{
"cell_type": "markdown",
"id": "fdbb9502-2e71-4e1e-9b7d-5bd464d27441",
"metadata": {},
"source": [
"Inverse to padding, it is also possible to truncate overly long values to a specific number of characters.\n",
"\n",
"The number behind a `.` in the format specifies the precision of the output. For strings, that means that the output is truncated to the specified length. In our example, this would be 5 characters."
]
},
{
"cell_type": "code",
"execution_count": 32,
"id": "a4fc48b0-0829-4493-8ec7-1ea111ccd737",
"metadata": {},
"outputs": [],
"source": [
"instrument = \"xylophone\""
]
},
{
"cell_type": "code",
"execution_count": 33,
"id": "8f1bfd2b-b280-4ed0-bb87-71bf030bba93",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"'xylop'"
]
},
"execution_count": 33,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"f\"{instrument:.5}\""
]
},
{
"cell_type": "markdown",
"id": "dc7432f0-3328-4c15-92be-8c885722fdcc",
"metadata": {},
"source": [
"### Combining truncating and padding\n",
"It is also possible to combine truncating and padding:"
]
},
{
"cell_type": "code",
"execution_count": 34,
"id": "cabe36fa-daba-4a26-88fb-6ca279c0831a",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"'xylop '"
]
},
"execution_count": 34,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"f\"{instrument:10.5}\""
]
},
{
"cell_type": "markdown",
"id": "48e16407-16ca-4e38-aedf-4dd856c83031",
"metadata": {},
"source": [
"## Numbers\n",
"\n",
"Integers:"
]
},
{
"cell_type": "code",
"execution_count": 35,
"id": "a1bb3bf3-462e-4993-854f-cb292e7e31d5",
"metadata": {},
"outputs": [],
"source": [
"answer = 42"
]
},
{
"cell_type": "code",
"execution_count": 36,
"id": "4f407c73-29ea-4eb0-a978-6aa8c31a1f77",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"'42'"
]
},
"execution_count": 36,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"f\"{answer:d}\""
]
},
{
"cell_type": "markdown",
"id": "f9c96d71-5837-4b0f-9c7b-ae4b405f1970",
"metadata": {},
"source": [
"Floats:"
]
},
{
"cell_type": "code",
"execution_count": 37,
"id": "205f5c1d-8524-4107-b180-ac9233620bc6",
"metadata": {},
"outputs": [],
"source": [
"import math"
]
},
{
"cell_type": "code",
"execution_count": 38,
"id": "20d9f414-52fe-4e9d-9a61-6d692acf7f3c",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"'3.141593'"
]
},
"execution_count": 38,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"f\"{math.pi:f}\""
]
},
{
"cell_type": "markdown",
"id": "e052926e-4da8-4156-ba1e-d55296ad194a",
"metadata": {},
"source": [
"### Other number representations"
]
},
{
"cell_type": "markdown",
"id": "15fcd36c-ed7f-4aca-a98b-49b0fd6b726e",
"metadata": {},
"source": [
"Numbers can also be represented in other bases, such as octal:"
]
},
{
"cell_type": "code",
"execution_count": 39,
"id": "39816a82-daae-435e-ac56-412ea7a49517",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"'52'"
]
},
"execution_count": 39,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"f\"{answer:o}\""
]
},
{
"cell_type": "markdown",
"id": "2ffc3f8a-e3c7-4c33-a497-ebd420c967cc",
"metadata": {},
"source": [
"hexadecimal (lower- or uppercase):"
]
},
{
"cell_type": "code",
"execution_count": 40,
"id": "cf13cc3f-7b2c-4818-a0a0-7a2325a73d83",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"'2a, 2A'"
]
},
"execution_count": 40,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"f\"{answer:x}, {answer:X}\""
]
},
{
"cell_type": "markdown",
"id": "6f82cc3e-715c-4dcc-b670-5d5eb50368f6",
"metadata": {},
"source": [
"or binary:"
]
},
{
"cell_type": "code",
"execution_count": 41,
"id": "b138b6c7-dc5f-4126-bfc7-54d72961e7fe",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"'101010'"
]
},
"execution_count": 41,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"f\"{answer:b}\""
]
},
{
"cell_type": "markdown",
"id": "9d028c99-672f-41e9-9099-8828c7978770",
"metadata": {},
"source": [
"A `#` can be used to add a suitable prefix (`0o`, `0x` and `0b`, respectively):"
]
},
{
"cell_type": "code",
"execution_count": 42,
"id": "3c765962-9d9d-440f-9073-99315f1555c2",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"'0x2a'"
]
},
"execution_count": 42,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"f\"{answer:#x}\""
]
},
{
"cell_type": "markdown",
"id": "57d7b5a7-e405-466b-8e59-63f088f08a3f",
"metadata": {},
"source": [
"Some other representations are available too, such as converting the number into an unicode character:"
]
},
{
"cell_type": "code",
"execution_count": 43,
"id": "169db28b-357f-40d6-92c9-032e471b26bd",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"'*'"
]
},
"execution_count": 43,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"f\"{answer:c}\""
]
},
{
"cell_type": "markdown",
"id": "558c9ca4-e696-4413-841e-62611308edcc",
"metadata": {},
"source": [
"displaying it in scientific notation (`E` instead of `e` for uppercase):"
]
},
{
"cell_type": "code",
"execution_count": 44,
"id": "f3b23164-714a-40fe-ab8d-4d70e7530c54",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"'9.682652e+12'"
]
},
"execution_count": 44,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"f\"{answer ** 8:e}\""
]
},
{
"cell_type": "markdown",
"id": "4d78a817-92df-479c-9fc5-83fc6444097a",
"metadata": {},
"source": [
"or selecting scientific notation automatically for larger numbers (`G` instead of `g` for uppercase):"
]
},
{
"cell_type": "code",
"execution_count": 45,
"id": "b294ef58-b1cd-4d25-ae68-4a435445c4a9",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"'42, 9.68265e+12'"
]
},
"execution_count": 45,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"f\"{answer:g}, {answer ** 8:g}\""
]
},
{
"cell_type": "markdown",
"id": "a387283c-af1c-44bb-bbd2-34decbe64203",
"metadata": {},
"source": [
"### Padding and truncating numbers"
]
},
{
"cell_type": "markdown",
"id": "e0c13c8f-5517-4f96-998a-108a53cdacae",
"metadata": {},
"source": [
"Similar to strings, numbers can also be constrained to a specific width."
]
},
{
"cell_type": "code",
"execution_count": 46,
"id": "4bc862b7-6b40-403e-ae7c-7f42f3e8bd76",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"' 42'"
]
},
"execution_count": 46,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"f\"{answer:4d}\""
]
},
{
"cell_type": "markdown",
"id": "eb64d9ae-744f-4d9e-901e-740fc17e9f82",
"metadata": {},
"source": [
"Like for strings, the padding character can be selected:"
]
},
{
"cell_type": "code",
"execution_count": 47,
"id": "4bb6764d-fdcf-4e7d-a50c-dd946b24e02b",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"'0042'"
]
},
"execution_count": 47,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"f\"{answer:04d}\""
]
},
{
"cell_type": "markdown",
"id": "d1b004cd-cba4-4fc6-aa46-77e5cb7d1d3d",
"metadata": {},
"source": [
"Again similar to truncating strings, the precision for floating point numbers limits the number of positions after the decimal point.\n",
"\n",
"For floating points, the padding value represents the length of the complete output. In the example below, we want our output to have at least 6 characters, with 2 after the decimal point."
]
},
{
"cell_type": "code",
"execution_count": 48,
"id": "292406cc-19ca-4287-b794-b7ff9f26356a",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"'003.14'"
]
},
"execution_count": 48,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"f\"{math.pi:06.2f}\""
]
},
{
"cell_type": "markdown",
"id": "0cfba235-8647-4cab-9164-b2307a2362bb",
"metadata": {},
"source": [
"For integer values, providing a precision doesn't make much sense and results in a ValueError:"
]
},
{
"cell_type": "code",
"execution_count": 50,
"id": "303f4d0e-25ad-4311-82fc-49204db30dd8",
"metadata": {},
"outputs": [
{
"ename": "ValueError",
"evalue": "Precision not allowed in integer format specifier",
"output_type": "error",
"traceback": [
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
"\u001b[0;31mValueError\u001b[0m Traceback (most recent call last)",
"Input \u001b[0;32mIn [50]\u001b[0m, in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[38;5;124mf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;132;01m{\u001b[39;00manswer\u001b[38;5;132;01m:\u001b[39;00m\u001b[38;5;124m06.2d\u001b[39m\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m\"\u001b[39m\n",
"\u001b[0;31mValueError\u001b[0m: Precision not allowed in integer format specifier"
]
}
],
"source": [
"f\"{answer:06.2d}\""
]
},
{
"cell_type": "markdown",
"id": "66d51d3f-80df-4228-b0f5-4f6ad34540c1",
"metadata": {
"tags": []
},
"source": [
"### Signed numbers\n",
"\n",
"By default, only negative numbers are prefixed with a sign. This can be changed of course."
]
},
{
"cell_type": "code",
"execution_count": 51,
"id": "c53dbad5-66e5-4123-9fe3-912af9154bed",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"'+42'"
]
},
"execution_count": 51,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"f\"{answer:+d}\""
]
},
{
"cell_type": "markdown",
"id": "9832198c-895b-4c46-a376-3c118215f1cb",
"metadata": {},
"source": [
"Use a space character to indicate that negative numbers should be prefixed with a minus symbol and a leading space should be used for positive ones.\n",
"\n"
]
},
{
"cell_type": "code",
"execution_count": 52,
"id": "f21f9eee-7770-4911-bf83-830b3aa3049a",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"' 42'"
]
},
"execution_count": 52,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"f\"{answer: d}\""
]
},
{
"cell_type": "code",
"execution_count": 53,
"id": "0b111ae5-e244-421b-8e20-eb109ea96566",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"'-42'"
]
},
"execution_count": 53,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"f\"{-answer: d}\""
]
},
{
"cell_type": "markdown",
"id": "f5c8c1cf-62f1-44ce-9675-4484f28e4e65",
"metadata": {},
"source": [
"It's also possible to control the position of the sign symbol relative to the padding."
]
},
{
"cell_type": "code",
"execution_count": 54,
"id": "eaefd680-9569-4c38-a173-4f261e0bdfc0",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"'- 42'"
]
},
"execution_count": 54,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"f\"{-answer:=5d}\""
]
},
{
"cell_type": "code",
"execution_count": 55,
"id": "efce8037-bf00-4b35-89d7-d6e9c9cb7a97",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"'+ 42'"
]
},
"execution_count": 55,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"f\"{answer:=+5d}\""
]
},
{
"cell_type": "markdown",
"id": "ca9a03cf-9eff-4d3b-892f-959c101c03d4",
"metadata": {},
"source": [
"### Thousands separator"
]
},
{
"cell_type": "markdown",
"id": "52b90251-389c-483c-adc9-89ac99c777df",
"metadata": {},
"source": [
"It's possible to use either `,` or `_` as a thousands separator when displaying large numbers:"
]
},
{
"cell_type": "code",
"execution_count": 56,
"id": "af11a443-5fd1-42a5-8197-80b74af1ce15",
"metadata": {},
"outputs": [],
"source": [
"num = 1234567890"
]
},
{
"cell_type": "code",
"execution_count": 57,
"id": "bbbbea16-28ea-4d1e-823e-920ca4d435c2",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"'1234567890'"
]
},
"execution_count": 57,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"f\"{num:d}\""
]
},
{
"cell_type": "code",
"execution_count": 58,
"id": "6f420099-4edb-4fec-9aef-16fddfbd7ca7",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"'1,234,567,890'"
]
},
"execution_count": 58,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"f\"{num:,d}\""
]
},
{
"cell_type": "code",
"execution_count": 59,
"id": "94cad7e8-89d3-4ed7-b1e0-2e105ab6e5bc",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"'1_234_567_890'"
]
},
"execution_count": 59,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"f\"{num:_d}\""
]
},
{
"cell_type": "markdown",
"id": "a0bcd859-4083-4fd9-a0fc-f9b0b6e0281b",
"metadata": {},
"source": [
"## Additional topics"
]
},
{
"cell_type": "markdown",
"id": "36634337-0e84-4458-827c-0e248147b241",
"metadata": {},
"source": [
"### Datetime"
]
},
{
"cell_type": "markdown",
"id": "7380fd50-40d3-4170-9cce-06fe06e12cce",
"metadata": {},
"source": [
"Like `.format()`, f-strings also allow objects to control their own rendering. This for example allows datetime objects to be formatted inline:"
]
},
{
"cell_type": "code",
"execution_count": 60,
"id": "322c5fbb-5e5d-47fd-9106-c78eeb228c63",
"metadata": {},
"outputs": [],
"source": [
"from datetime import datetime\n",
"dt = datetime(2022, 4, 11, 13, 37)"
]
},
{
"cell_type": "code",
"execution_count": 61,
"id": "3f5993d3-9054-416d-80bb-dc2b2b66c36e",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"'2022-04-11 13:37'"
]
},
"execution_count": 61,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"f\"{dt:%Y-%m-%d %H:%M}\""
]
},
{
"cell_type": "markdown",
"id": "73a61cb4-2d6b-4dc3-87d9-2d70063f82fc",
"metadata": {},
"source": [
"### Parametrized formats"
]
},
{
"cell_type": "markdown",
"id": "1c3dc9b8-3bd7-4d79-a7da-e13eb2c3b117",
"metadata": {},
"source": [
"\n",
"Additionally, f-strings allow all of the components of the format to be specified dynamically using parametrization. Parametrized formats are nested expressions in braces that can appear anywhere in the parent format after the colon.\n",
"\n",
"Parametrized alignment and width:"
]
},
{
"cell_type": "code",
"execution_count": 62,
"id": "1471e2cb-3c4d-488d-aab5-eb52fffcbd0c",
"metadata": {},
"outputs": [],
"source": [
"value = \"test\"\n",
"align = \"^\"\n",
"width = 10"
]
},
{
"cell_type": "code",
"execution_count": 63,
"id": "b45a618b-a1cf-4e86-af49-0af164adb280",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"' test '"
]
},
"execution_count": 63,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"f'{value:{align}{width}}'"
]
},
{
"cell_type": "markdown",
"id": "9185d038-edcb-447e-b4af-cc0c6731c3a7",
"metadata": {},
"source": [
"Parametrized precision:\n",
"\n"
]
},
{
"cell_type": "code",
"execution_count": 64,
"id": "6f94b1d8-852f-40e1-8ecd-d612aa87e3a2",
"metadata": {},
"outputs": [],
"source": [
"value = \"pizza\"\n",
"prec = 2"
]
},
{
"cell_type": "code",
"execution_count": 65,
"id": "512a3eca-e7d6-4430-be27-bb778bc55c5d",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"'pi = 3.14'"
]
},
"execution_count": 65,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"f\"{value:.{prec}} = {math.pi:.{prec}f}\""
]
},
{
"cell_type": "markdown",
"id": "913cad87-ebc1-4e73-b34e-dbc103a902fa",
"metadata": {},
"source": [
"Width and precision:"
]
},
{
"cell_type": "code",
"execution_count": 66,
"id": "9c23f014-fc78-4e4a-a212-9332ebca9685",
"metadata": {},
"outputs": [],
"source": [
"width = 5"
]
},
{
"cell_type": "code",
"execution_count": 67,
"id": "be81f935-0fab-47ac-b4a1-fe7fd36f793e",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"' 3.14'"
]
},
"execution_count": 67,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"f\"{math.pi:{width}.{prec}f}\""
]
},
{
"cell_type": "markdown",
"id": "6eac74c9-9763-49dd-ab3a-3919f3e422ed",
"metadata": {},
"source": [
"The components of a date-time can be set separately:"
]
},
{
"cell_type": "code",
"execution_count": 68,
"id": "23b650d3-4991-4bb1-b66f-d4ae5f3baee9",
"metadata": {},
"outputs": [],
"source": [
"dfmt = \"%Y-%m-%d\"\n",
"tfmt = \"%H:%M\""
]
},
{
"cell_type": "code",
"execution_count": 69,
"id": "282d9f48-eaf2-4788-adac-6bcdcd13f4b8",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"'2022-04-11 13:37'"
]
},
"execution_count": 69,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"f\"{dt:{dfmt} {tfmt}}\""
]
},
{
"cell_type": "markdown",
"id": "147b4432-5994-49ed-9317-5e147b34dc9f",
"metadata": {},
"source": [
"### Custom objects\n",
"\n",
"The datetime example works through the use of the `__format__()` magic method. You can define custom format handling in your own objects by overriding this method. This gives you complete control over the format syntax used."
]
},
{
"cell_type": "code",
"execution_count": 70,
"id": "356eba92-0984-49bd-a89a-024186edd6b2",
"metadata": {},
"outputs": [],
"source": [
"class HAL9000:\n",
"\n",
" def __format__(self, fmt):\n",
" if fmt == \"open-the-pod-bay-doors\":\n",
" return \"I'm afraid I can't do that.\"\n",
" return \"HAL 9000\"\n",
" \n",
"hal9000 = HAL9000()"
]
},
{
"cell_type": "code",
"execution_count": 71,
"id": "41ca90d2-e2f6-4f03-a585-6ec12c034977",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"\"I'm afraid I can't do that.\""
]
},
"execution_count": 71,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"f\"{hal9000:open-the-pod-bay-doors}\""
]
},
{
"cell_type": "markdown",
"id": "3cb234bf-552b-4fd5-931d-da6c0dfd0cf0",
"metadata": {},
"source": [
"### Escaping braces"
]
},
{
"cell_type": "markdown",
"id": "76099f2d-6540-4b55-b21e-389a05199030",
"metadata": {},
"source": [
"To use `{` or `}` inside an f-string, double them:"
]
},
{
"cell_type": "code",
"execution_count": 72,
"id": "d4f116f5-5b72-4e90-b33d-5f5c34e10d6c",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"'Literal braces: {value}'"
]
},
"execution_count": 72,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"f\"Literal braces: {{value}}\""
]
},
{
"cell_type": "markdown",
"id": "4c67b52a-541b-440f-9c44-1693d45b35d8",
"metadata": {},
"source": [
"### Quotes usage\n",
"\n",
"[Starting with Python 3.12](https://docs.python.org/3.12/whatsnew/3.12.html#pep-701-syntactic-formalization-of-f-strings), nested quotes (as well as backslashes) are freely allowed inside of `{...}` in an f-string ([PEP 701 – Syntactic formalization of f-strings](https://peps.python.org/pep-0701/)).\n",
"\n",
"For Python versions before 3.12, if you need to use single quotes inside an f-string, the easiest way is to use double-quotes for the string (and vice-versa), like with ordinary strings:"
]
},
{
"cell_type": "code",
"execution_count": 73,
"id": "0dd2a5a5-5284-446d-8bcc-a703520c5a39",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"'\"Use fstrings\", he said!'"
]
},
"execution_count": 73,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"f\"I'm an fstring\"\n",
"f'\"Use fstrings\", he said!'"
]
},
{
"cell_type": "markdown",
"id": "ac49c8a9-abe4-4eae-a387-f9fc9649d7c1",
"metadata": {},
"source": [
"If you need to use single and double-quotes in the string, escape one of them - again, like with regular strings:"
]
},
{
"cell_type": "code",
"execution_count": 74,
"id": "df8b9b94-fc4a-4fb3-9da3-9e0dcf59cc33",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"'The string above contains: \"I\\'m an fstring\"'"
]
},
"execution_count": 74,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"f\"The string above contains: \\\"I'm an fstring\\\"\""
]
},
{
"cell_type": "markdown",
"id": "2b93c5e0-7034-4b3f-816f-5250bfe64a7a",
"metadata": {},
"source": [
"Things get a bit more troublesome when mixing quotes inside replacements: There, backslashes are not allowed. Usually, you can just use the other kind of string quotes, like we did in an earlier example:"
]
},
{
"cell_type": "code",
"execution_count": 75,
"id": "ee3dbbb4-db0a-49c6-a621-2d4e7c1794bb",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"'red: #ff0000'"
]
},
"execution_count": 75,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"f\"red: {colors['red']}\""
]
},
{
"cell_type": "markdown",
"id": "0923d9bf-3055-41f3-aaa2-205ab2c168a6",
"metadata": {},
"source": [
"Using the same quotes would end the string:"
]
},
{
"cell_type": "code",
"execution_count": 76,
"id": "c95a269c-726d-43cc-9395-c4b16044d042",
"metadata": {},
"outputs": [
{
"ename": "SyntaxError",
"evalue": "f-string: unmatched '[' (2824816191.py, line 1)",
"output_type": "error",
"traceback": [
"\u001b[0;36m Input \u001b[0;32mIn [76]\u001b[0;36m\u001b[0m\n\u001b[0;31m f\"red: {colors[\"red\"]}\" # WRONG\u001b[0m\n\u001b[0m ^\u001b[0m\n\u001b[0;31mSyntaxError\u001b[0m\u001b[0;31m:\u001b[0m f-string: unmatched '['\n"
]
}
],
"source": [
"f\"red: {colors[\"red\"]}\" # WRONG"
]
},
{
"cell_type": "markdown",
"id": "2a14cbd1-c688-44f8-b3d5-44097052401f",
"metadata": {},
"source": [
"And backslashes won't work either:"
]
},
{
"cell_type": "code",
"execution_count": 77,
"id": "38c16820-d380-4732-928f-ed3ba73b1c54",
"metadata": {},
"outputs": [
{
"ename": "SyntaxError",
"evalue": "f-string expression part cannot include a backslash (2449732094.py, line 1)",
"output_type": "error",
"traceback": [
"\u001b[0;36m Input \u001b[0;32mIn [77]\u001b[0;36m\u001b[0m\n\u001b[0;31m f\"red: {colors[\\\"red\\\"]}\" # WRONG\u001b[0m\n\u001b[0m ^\u001b[0m\n\u001b[0;31mSyntaxError\u001b[0m\u001b[0;31m:\u001b[0m f-string expression part cannot include a backslash\n"
]
}
],
"source": [
"f\"red: {colors[\\\"red\\\"]}\" # WRONG"
]
},
{
"cell_type": "markdown",
"id": "fa5cd6a4",
"metadata": {},
"source": [
"But triple-quotes work great:"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "da4c410c",
"metadata": {},
"outputs": [],
"source": [
"f\"\"\"red: {colors[\"red\"]}\"\"\""
]
},
{
"cell_type": "markdown",
"id": "1b299862-97a1-476e-b804-41158a426594",
"metadata": {},
"source": [
"Or you can use a temporary variable instead."
]
},
{
"cell_type": "markdown",
"id": "ad03b587-bfd9-4b5f-b44d-0543c02b3ab7",
"metadata": {},
"source": [
"### Switching to f-strings\n",
"\n",
"If you're still using `\"...\".format(...)` or the even older percentage-formatting (`\"...\" % ...`), tools like [pyupgrade](https://github.com/asottile/pyupgrade) or [flynt](https://github.com/ikamensh/flynt) can help switching to f-strings."
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.10.4"
},
"name": "fstring.help: Python f-string guide",
"title": "fstring.help: Python f-string guide"
},
"nbformat": 4,
"nbformat_minor": 5
}
|