{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# f-strings\n", "\n", "[f-strings](https://www.python.org/dev/peps/pep-0498/)\n", "are\n", "[new in Python 3.6](https://docs.python.org/3.6/whatsnew/3.6.html#pep-498-formatted-string-literals).\n", "\n", "f-strings look like an ordinary strings with an f in front.\n", "They look like an ordinary (immutable) string that does not change,\n", "but they are not immutable strings.\n", "\n", "# **They are dynamic expressions!!!**\n", "\n", "One can put expressions within curly braces in an f-string,\n", "and the expressions will be evaluated each time,\n", "and then converted to a string.\n", "The most common expressions used are just variable names.\n", "\n", "It is a more\n", "[DRY](https://en.wikipedia.org/wiki/Don't_repeat_yourself)\n", "way of doing formatting than str.format." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Follow [80/20 rule](https://en.wikipedia.org/wiki/Pareto_principle).\n", "\n", "So avoid covering complicated stuff and edge cases:\n", "- format specifiers\n", "- curly braces within the f-string\n", "- nested f-strings" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "---\n", "\n", "Let's look at how formatting is often done with the\n", "[str.format](https://docs.python.org/3/library/stdtypes.html#str.format)\n", "method, then see how formatting is done with\n", "[f-strings](https://www.python.org/dev/peps/pep-0498/)." ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "collapsed": true }, "outputs": [], "source": [ "stuff = {\n", " 'apple': 1.97,\n", " 'banana': 2.99,\n", " 'cherry': 3.99,\n", "}" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "The price of apple is 1.97.\n", "The price of banana is 2.99.\n", "The price of cherry is 3.99.\n" ] } ], "source": [ "# Common pattern of .format use: use numerical indexes\n", "\n", "for name, price in stuff.items():\n", " print('The price of {0} is {1}.'.format(name, price))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In 'The price of {0} is {1}' above,\n", "one must read back and forth to match\n", "the numerical indexes in the string\n", "with the .format method arguments.\n", "Having to figure out what the numerical indexes are for hurts readability.\n", "\n", "Which leads to a better way below\n", "using named arguments to the .format method\n", "so that meaning is obvious in the format string." ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "The price of apple is 1.97.\n", "The price of banana is 2.99.\n", "The price of cherry is 3.99.\n" ] } ], "source": [ "# Common pattern of .format use: use parameter names\n", "\n", "for name, price in stuff.items():\n", " print(\n", " 'The price of {name} is {price}.'.\n", " format(name=name, price=price))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Something that sucks about the above print,\n", "is that name and price appear three times each.\n", "I.e., It is not\n", "[DRY](https://en.wikipedia.org/wiki/Don't_repeat_yourself).\n", "\n", "With f-strings, name and price only have to appear once,\n", "making the code easier to read and maintain\n", "as in the following example." ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "The price of apple is 1.97.\n", "The price of banana is 2.99.\n", "The price of cherry is 3.99.\n" ] } ], "source": [ "for name, price in stuff.items():\n", " print(f'The price of {name} is {price}.')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "It reminds me of shell syntax. For example,\n", "\n", " echo \"The price of ${name} is ${price}\"\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "It gets better. One may put expressions\n", "within the curly braces in an f-string.\n", "One is not limited to using just variable names." ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "The total price of apple is 2.96.\n", "The total price of banana is 4.49.\n", "The total price of cherry is 5.99.\n" ] } ], "source": [ "tax_rate = 0.50\n", "\n", "for name, price in stuff.items():\n", " print(f'The total price of {name} is {round(price * (1+tax_rate), 2)}.')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "But what does round(price * (1+tax_rate), 2) mean? \n", "What is it for?\n", "Just because you can put expressions in a f-string\n", "does not mean that you should.\n", "\n", "In the cell below, a temporary variable is used for documentation\n", "to make the code easier to read." ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "The total price of apple is 2.96.\n", "The total price of banana is 4.49.\n", "The total price of cherry is 5.99.\n" ] } ], "source": [ "tax_rate = 0.50\n", "\n", "for name, price in stuff.items():\n", " total_price = round(price * (1+tax_rate), 2)\n", " print(f'The total price of {name} is {total_price}.')" ] } ], "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.0" } }, "nbformat": 4, "nbformat_minor": 0 }