{ "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 %s to inject strings into your print statements. The modulo `%` is referred to as a \"string formatting operator\"." ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "I'm going to inject something here.\n" ] } ], "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": 2, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "I'm going to inject some text here, and more text here.\n" ] } ], "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": 3, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "I'm going to inject some text here, and more text here.\n" ] } ], "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 %s and %r 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": 4, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "He said his name was Fred.\n", "He said his name was 'Fred'.\n" ] } ], "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": 5, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "I once caught a fish this \tbig.\n", "I once caught a fish 'this \\tbig'.\n" ] } ], "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": 6, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "I wrote 3.75 programs today.\n", "I wrote 3 programs today.\n" ] } ], "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 %5.2f. Here, 5 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, .2f stands for how many numbers to show past the decimal point. Let's see some examples:" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Floating point numbers: 13.14\n" ] } ], "source": [ "print('Floating point numbers: %5.2f' %(13.144))" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Floating point numbers: 13\n" ] } ], "source": [ "print('Floating point numbers: %1.0f' %(13.144))" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Floating point numbers: 13.14400\n" ] } ], "source": [ "print('Floating point numbers: %1.5f' %(13.144))" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Floating point numbers: 13.14\n" ] } ], "source": [ "print('Floating point numbers: %10.2f' %(13.144))" ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Floating point numbers: 13.14\n" ] } ], "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": 12, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "First: hi!, Second: 3.14, Third: 'bye!'\n" ] } ], "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": 13, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "This is a string with an insert\n" ] } ], "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": 14, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "The quick brown fox\n" ] } ], "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": 15, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "First Object: 1, Second Object: Two, Third Object: 12.3\n" ] } ], "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": 16, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "A penny saved is a penny earned.\n", "A penny saved is a penny earned.\n" ] } ], "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": 17, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Fruit | Quantity \n", "Apples | 3.0\n", "Oranges | 10\n" ] } ], "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": 18, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Left | Center | Right\n", "11 | 22 | 33\n" ] } ], "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": 19, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Left==== | -Center- | ...Right\n", "11====== | ---22--- | ......33\n" ] } ], "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": 20, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "This is my ten-character, two-decimal number: 13.58\n", "This is my ten-character, two-decimal number: 13.58\n" ] } ], "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": 21, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "He said his name is Fred.\n" ] } ], "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": 22, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "He said his name is 'Fred'\n" ] } ], "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": 23, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "My 10 character, four decimal number is: 23.4568\n", "My 10 character, four decimal number is: 23.4568\n" ] } ], "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": 24, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "My 10 character, four decimal number is: 23.4500\n", "My 10 character, four decimal number is: 23.45\n" ] } ], "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": 25, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "My 10 character, four decimal number is: 23.4500\n", "My 10 character, four decimal number is: 23.4500\n" ] } ], "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!" ] } ], "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.6.2" } }, "nbformat": 4, "nbformat_minor": 1 }