Files
labs/Module-2/1.Basic/03-Print Formatting with Strings.ipynb
T

523 lines
13 KiB
Plaintext

{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# String Formatting\n",
"\n",
"String formatting lets you inject items into a string rather than trying to chain items together using commas or string concatenation. As a quick comparison, consider:\n",
"\n",
" player = 'Thomas'\n",
" points = 33\n",
" \n",
" 'Last night, '+player+' scored '+str(points)+' points.' # concatenation\n",
" \n",
" f'Last night, {player} scored {points} points.' # string formatting\n",
"\n",
"\n",
"There are three ways to perform string formatting.\n",
"* The oldest method involves placeholders using the modulo `%` character.\n",
"* An improved technique uses the `.format()` string method.\n",
"* The newest method, introduced with Python 3.6, uses formatted string literals, called *f-strings*.\n",
"\n",
"Since you will likely encounter all three versions in someone else's code, we describe each of them here."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Formatting with placeholders\n",
"You can use <code>%s</code> to inject strings into your print statements. The modulo `%` is referred to as a \"string formatting operator\"."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"print(\"I'm going to inject %s here.\" %'something')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"You can pass multiple items by placing them inside a tuple after the `%` operator."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"print(\"I'm going to inject %s text here, and %s text here.\" %('some','more'))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"You can also pass variable names:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"x, y = 'some', 'more'\n",
"print(\"I'm going to inject %s text here, and %s text here.\"%(x,y))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Format conversion methods.\n",
"It should be noted that two methods <code>%s</code> and <code>%r</code> convert any python object to a string using two separate methods: `str()` and `repr()`. We will learn more about these functions later on in the course, but you should note that `%r` and `repr()` deliver the *string representation* of the object, including quotation marks and any escape characters."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"print('He said his name was %s.' %'Fred')\n",
"print('He said his name was %r.' %'Fred')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"As another example, `\\t` inserts a tab into a string."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"print('I once caught a fish %s.' %'this \\tbig')\n",
"print('I once caught a fish %r.' %'this \\tbig')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The `%s` operator converts whatever it sees into a string, including integers and floats. The `%d` operator converts numbers to integers first, without rounding. Note the difference below:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"print('I wrote %s programs today.' %3.75)\n",
"print('I wrote %d programs today.' %3.75) "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Padding and Precision of Floating Point Numbers\n",
"Floating point numbers use the format <code>%5.2f</code>. Here, <code>5</code> would be the minimum number of characters the string should contain; these may be padded with whitespace if the entire number does not have this many digits. Next to this, <code>.2f</code> stands for how many numbers to show past the decimal point. Let's see some examples:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"print('Floating point numbers: %5.2f' %(13.144))"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"print('Floating point numbers: %1.0f' %(13.144))"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"print('Floating point numbers: %1.5f' %(13.144))"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"print('Floating point numbers: %10.2f' %(13.144))"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"print('Floating point numbers: %25.2f' %(13.144))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"For more information on string formatting with placeholders visit https://docs.python.org/3/library/stdtypes.html#old-string-formatting"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Multiple Formatting\n",
"Nothing prohibits using more than one conversion tool in the same print statement:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"print('First: %s, Second: %5.2f, Third: %r' %('hi!',3.1415,'bye!'))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Formatting with the `.format()` method\n",
"A better way to format objects into your strings for print statements is with the string `.format()` method. The syntax is:\n",
"\n",
" 'String here {} then also {}'.format('something1','something2')\n",
" \n",
"For example:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"print('This is a string with an {}'.format('insert'))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### The .format() method has several advantages over the %s placeholder method:"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### 1. Inserted objects can be called by index position:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"print('The {2} {1} {0}'.format('fox','brown','quick'))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### 2. Inserted objects can be assigned keywords:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"print('First Object: {a}, Second Object: {b}, Third Object: {c}'.format(a=1,b='Two',c=12.3))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### 3. Inserted objects can be reused, avoiding duplication:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"print('A %s saved is a %s earned.' %('penny','penny'))\n",
"# vs.\n",
"print('A {p} saved is a {p} earned.'.format(p='penny'))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Alignment, padding and precision with `.format()`\n",
"Within the curly braces you can assign field lengths, left/right alignments, rounding parameters and more"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"print('{0:8} | {1:9}'.format('Fruit', 'Quantity'))\n",
"print('{0:8} | {1:9}'.format('Apples', 3.))\n",
"print('{0:8} | {1:9}'.format('Oranges', 10))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"By default, `.format()` aligns text to the left, numbers to the right. You can pass an optional `<`,`^`, or `>` to set a left, center or right alignment:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"print('{0:<8} | {1:^8} | {2:>8}'.format('Left','Center','Right'))\n",
"print('{0:<8} | {1:^8} | {2:>8}'.format(11,22,33))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"You can precede the aligment operator with a padding character"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"print('{0:=<8} | {1:-^8} | {2:.>8}'.format('Left','Center','Right'))\n",
"print('{0:=<8} | {1:-^8} | {2:.>8}'.format(11,22,33))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Field widths and float precision are handled in a way similar to placeholders. The following two print statements are equivalent:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"print('This is my ten-character, two-decimal number:%10.2f' %13.579)\n",
"print('This is my ten-character, two-decimal number:{0:10.2f}'.format(13.579))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Note that there are 5 spaces following the colon, and 5 characters taken up by 13.58, for a total of ten characters.\n",
"\n",
"For more information on the string `.format()` method visit https://docs.python.org/3/library/string.html#formatstrings"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Formatted String Literals (f-strings)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Introduced in Python 3.6, f-strings offer several benefits over the older `.format()` string method described above. For one, you can bring outside variables immediately into to the string rather than pass them as arguments through `.format(var)`."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"name = 'Fred'\n",
"\n",
"print(f\"He said his name is {name}.\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Pass `!r` to get the string representation:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"print(f\"He said his name is {name!r}\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Float formatting follows `\"result: {value:{width}.{precision}}\"`"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Where with the `.format()` method you might see `{value:10.4f}`, with f-strings this can become `{value:{10}.{6}}`\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"num = 23.45678\n",
"print(\"My 10 character, four decimal number is:{0:10.4f}\".format(num))\n",
"print(f\"My 10 character, four decimal number is:{num:{10}.{6}}\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Note that with f-strings, *precision* refers to the total number of digits, not just those following the decimal. This fits more closely with scientific notation and statistical analysis. Unfortunately, f-strings do not pad to the right of the decimal, even if precision allows it:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"num = 23.45\n",
"print(\"My 10 character, four decimal number is:{0:10.4f}\".format(num))\n",
"print(f\"My 10 character, four decimal number is:{num:{10}.{6}}\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"If this becomes important, you can always use `.format()` method syntax inside an f-string:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"num = 23.45\n",
"print(\"My 10 character, four decimal number is:{0:10.4f}\".format(num))\n",
"print(f\"My 10 character, four decimal number is:{num:10.4f}\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"For more info on formatted string literals visit https://docs.python.org/3/reference/lexical_analysis.html#f-strings"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"That is the basics of string formatting!"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"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.8.8"
},
"widgets": {
"application/vnd.jupyter.widget-state+json": {
"state": {},
"version_major": 2,
"version_minor": 0
}
}
},
"nbformat": 4,
"nbformat_minor": 4
}