{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Программирование и анализ данных" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "*Алла Тамбовцева, НИУ ВШЭ*" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Форматирование строк (string formatting)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "А теперь посмотрим на то, как подставлять значения в уже имеющийся текстовый шаблон, то есть форматировать строки. Чтобы понять, о чём идет речь, можно представить, что у нас есть электронная анкета, которую заполняет пользователь, и мы должны написать программу, которая выводит на экран введенные данные, чтобы пользователь мог их проверить.\n", "\n", "Пусть для начала пользователь вводит свое имя и возраст." ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Введите Ваше имя: Алла\n", "Введите Ваш возраст: 25\n" ] } ], "source": [ "name = input(\"Введите Ваше имя: \")\n", "age = int(input(\"Введите Ваш возраст: \")) # возраст будет целочисленным" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Теперь выведем на экран сообщение вида \n", "\n", " Ваше имя: `имя`. Ваш возраст: `возраст`. " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Но прежде, чем это сделать, поймем, какого типа будут значения, которые мы будем подставлять в шаблон. Имя (переменная `name`) – это строка (*string*), а возраст (переменная `age`) – это целое число (*integer*)." ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Ваше имя: Алла. Ваш возраст: 25.\n" ] } ], "source": [ "result = \"Ваше имя: %s. Ваш возраст: %i.\" % (name, age)\n", "print(result)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Что за таинственные `%s` и `%i`? Все просто: оператор `%` в строке указывает место, на которое будет подставляться значение, а буква сразу после процента – сокращённое название типа данных (`s` – от *string* и `i` – от *integer*). Осталось только сообщить Python, что именно нужно подставлять – после кавычек поставить `%` и в скобках перечислить названия переменных, значения которых мы будем подставлять. \n", "\n", "Для тех, кто работал в R: форматирование строк с помощью оператора `%` – аналог форматирования с помощью функции `sprintf()` в R. \n", "\n", "Конечно, результат можно выводить сразу, не сохраняя полученную строку в переменную. Главное, не запутаться в скобках, и не потерять их." ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Ваше имя: Алла. Ваш возраст: 25.\n" ] } ], "source": [ "print(\"Ваше имя: %s. Ваш возраст: %i.\" % (name, age))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "*Примечание:* не теряйте часть с переменными после самой строки. Иначе получится нечто странное:" ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Ваше имя: %s. Ваш возраст: %i.\n" ] } ], "source": [ "print(\"Ваше имя: %s. Ваш возраст: %i.\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Важно помнить, что если мы забудем указать какую-то из переменных, мы получим ошибку (точнее, исключение): Python не будет знать, откуда брать нужные значения. " ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [ { "ename": "TypeError", "evalue": "not enough arguments for format string", "output_type": "error", "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mTypeError\u001b[0m Traceback (most recent call last)", "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"Ваше имя: %s. Ваш возраст: %i.\"\u001b[0m \u001b[0;34m%\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0mname\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", "\u001b[0;31mTypeError\u001b[0m: not enough arguments for format string" ] } ], "source": [ "print(\"Ваше имя: %s. Ваш возраст: %i.\" % (name))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Кроме того, создавая такие текстовые шаблоны, нужно обращать внимание на типы переменных, значения которых мы подставляем. " ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Ваше имя: Алла. Ваш возраст: 25.\n" ] } ], "source": [ "print(\"Ваше имя: %s. Ваш возраст: %s.\" % (name, age)) # так сработает" ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [ { "ename": "TypeError", "evalue": "%i format: a number is required, not str", "output_type": "error", "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mTypeError\u001b[0m Traceback (most recent call last)", "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"Ваше имя: %i. Ваш возраст: %s.\"\u001b[0m \u001b[0;34m%\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0mname\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mage\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;31m# а так нет\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", "\u001b[0;31mTypeError\u001b[0m: %i format: a number is required, not str" ] } ], "source": [ "print(\"Ваше имя: %i. Ваш возраст: %s.\" % (name, age)) # а так нет" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "В первом случае код сработал: Python не очень строго относится к типам данных, и поэтому он легко может превратить целочисленный возраст в строку (два `%s` вместо `%s` и `%i` не является помехой). Во втором случае все иначе. Превратить строку, которая состоит из букв (`name`) в целое число никак не получится, поэтому Python справедливо ругается." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "А что будет, если мы будем подставлять не целое число, а дробное, с плавающей точкой? Попробуем!" ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Введите Ваш рост (в метрах): 1.68\n" ] }, { "data": { "text/plain": [ "1.68" ] }, "execution_count": 16, "metadata": {}, "output_type": "execute_result" } ], "source": [ "height = float(input(\"Введите Ваш рост (в метрах): \"))\n", "height" ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Ваш рост: 1.680000 м.\n" ] } ], "source": [ "print(\"Ваш рост: %f м.\" % height) # f - от float" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "По умолчанию при подстановке значений типа *float* Python выводит число с шестью знаками после запятой. Но это можно исправить. Перед `f` нужно поставить точку и указать число знаков после запятой, которое мы хотим:" ] }, { "cell_type": "code", "execution_count": 18, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Ваш рост: 1.68 м.\n" ] } ], "source": [ "print(\"Ваш рост: %.2f м.\" % height) # например, два" ] }, { "cell_type": "code", "execution_count": 19, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Ваш рост: 1.7 м. \n" ] } ], "source": [ "print(\"Ваш рост: %.1f м. \" % height) # или один" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "В случае, если указанное число знаков после запятой меньше, чем есть на самом деле (как в ячейке выше), происходит обычное арифметическое округление." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Рассмотренный выше способ форматирования строк – не единственный. Он довольно стандартный, но при этом немного устаревший. В Python 3 есть другой способ ‒ форматирование с помощью метода `.format()`. Кроме того, в Python 3.6 и более поздних версиях появился еще более продвинутый способ форматирования строк ‒ *f-strings* *(formatted string literals)*. \n", "\n", "F-strings очень удобны и просты в использовании: вместо `%` и сокращённого названия типа в фигурных скобках внутри текстового шаблона нужно указать название переменной, из которой должно подставляться значение, а перед всей строкой добавить `f`, чтобы Python знал, что нам нужна именно *f-string*." ] }, { "cell_type": "code", "execution_count": 20, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Ваше имя: Алла. Ваш возраст: 25\n" ] } ], "source": [ "print(f\"Ваше имя: {name}. Ваш возраст: {age}\")" ] } ], "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.8" } }, "nbformat": 4, "nbformat_minor": 2 }