{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "# Типы и модель данных\n", "\n", " \n", "**С.В. Лемешевский** (email: `sergey.lemeshevsky@gmail.com`), Институт математики НАН Беларуси\n", "\n", "Date: **Mar 18, 2020**\n", "\n", "\n", "\n", "\n", "\n", "\n", "Здесь разберем как Python работает с переменными и определим, какие\n", "типы данных можно использовать в рамках этого языка. Подробно рассмотрим модель\n", "данных Python, а также механизмы создания и изменения значения\n", "переменных." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Кратко о типизации языков программирования\n", "
\n", "\n", "Если достаточно формально подходить к вопросу о типизации языка Python, то\n", "можно сказать, что он относится к языкам с неявной сильной динамической\n", "типизацией.\n", "\n", "Неявная типизация означает, что при объявлении переменной вам не нужно\n", "указывать её тип, при явной – это делать необходимо. В качестве примера языков с\n", "явной типизацией можно привести Java, C++ . Вот как будет выглядеть объявление\n", "целочисленной переменной в Java и Python.\n", "\n", "* Java:" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ " int a = 1 ;\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "* Python:" ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "collapsed": false, "jupyter": { "outputs_hidden": false } }, "outputs": [], "source": [ "a = 1" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "\n", "\n", "\n", "# Типы данных в Python\n", "
\n", "\n", "В Python типы данных можно разделить на встроенные в интерпретатор (`built-in`) и\n", "не встроенные, которые можно использовать при импортировании соответствующих\n", "модулей.\n", "\n", "К основным встроенным типам относятся:\n", "1. `None` (неопределенное значение переменной)\n", "\n", "2. Логические переменные (`Boolean Type`)\n", "\n", "3. Числа (`Numeric Type`)\n", "\n", "a. `int` – целое число\n", "\n", "b. `float` – число с плавающей точкой\n", "\n", "c. `complex` – комплексное число\n", "\n", "\n", "4. Списки (`Sequence Type`)\n", "\n", "a. `list` – список\n", "\n", "b. `tuple` – кортеж\n", "\n", "c. `range` – диапазон\n", "\n", "\n", "4. Строки (`Text Sequence Type`)\n", "\n", "a. `str`\n", "\n", "\n", "2. Бинарные списки ( Binary Sequence Types )\n", "\n", "a. `bytes` – байты\n", "\n", "b. `bytearray` – массивы байт\n", "\n", "c. `memoryview` – специальные объекты для доступа к внутренним данным объекта через `protocol buffer`\n", "\n", "\n", "4. Множества (`Set Types`)\n", "\n", "a. `set` – множество\n", "\n", "b. `frozenset` – неизменяемое множество\n", "\n", "\n", "3. Словари (`Mapping Types`)\n", "\n", "a. `dict` – словарь\n", "\n", "\n", "\n", "" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Модель данных\n", "
\n", "\n", "Рассмотрим как создаются объекты в памяти, их устройство, процесс объявления\n", "новых переменных и работу операции присваивания.\n", "\n", "Для того, чтобы объявить и сразу инициализировать переменную необходимо\n", "написать её имя, потом поставить знак равенства и значение, с которым эта\n", "переменная будет создана.\n", "\n", "Например строка:" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "collapsed": false, "jupyter": { "outputs_hidden": false } }, "outputs": [], "source": [ "b = 5" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Объявляет переменную `b` и присваивает ей значение `5`.\n", "\n", "Целочисленное значение `5` в рамках языка Python по сути своей является\n", "*объектом*. Объект, в данном случае – это абстракция для представления данных,\n", "данные – это числа, списки, строки и т.п. При этом, под *данными* следует понимать как\n", "непосредственно сами объекты, так и отношения между ними (об этом чуть позже).\n", "Каждый объект имеет три атрибута – это *идентификатор*, *значение* и *тип*.\n", "\n", "*Идентификатор* – это уникальный признак объекта, позволяющий отличать объекты\n", "друг от друга, а *значение* – непосредственно информация, хранящаяся в памяти,\n", "которой управляет интерпретатор. \n", "\n", "При инициализации переменной, на уровне интерпретатора, происходит\n", "следующее:\n", "* создается целочисленный объект `5` (можно представить, что в этот момент создается ячейка и число `5` «кладется» в эту ячейку);\n", "\n", "* данный объект имеет некоторый идентификатор, значение: `5`, и тип: целое число;\n", "\n", "* посредством оператора `=` создается ссылка между переменной `b` и целочисленным объектом `5` (переменная `b` ссылается на объект `5`).\n", "\n", "> **Об именах переменных.**\n", ">\n", "> Допустимые имена переменных в языке Python – это последовательность\n", "> символов произвольной длины, содержащей «начальный символ»\n", "> и ноль или более «символов продолжения». Имя переменной должно\n", "> следовать определенным правилам и соглашениям. \n", "> \n", "> Первое правило касается начального символа и символов\n", "> продолжения. Начальным символом может быть любой символ, который в\n", "> кодировке Юникод рассматривается как принадлежащий диапазону\n", "> алфавитных символов ASCII (`a`, `b`, ..., `z`, `A`, `B`, ..., `Z`),\n", "> символ подчеркивания (`_`), а также символы большинства национальных\n", "> (не английских) алфавитов. Каждый символ продолжения может быть\n", "> любым символом из тех, что пригодны в качестве начального символа,\n", "> а также любым непробельным символом, включая символы, которые\n", "> в кодировке Юникод считаются цифрами, такие как (`0`, `1`, ...,\n", "> `9`), и символ Каталана `·`. Идентификаторы чувствительны к регистру,\n", "> поэтому `TAXRATE`, `Taxrate`, `TaxRate`, `taxRate` и `taxrate` – это\n", "> пять разных переменных. \n", "> \n", "> Имя переменной не должно совпадать с ключевыми словами интерпретатора\n", "> Python. Список ключевых слов можно получить непосредственно в программе, для\n", "> этого нужно подключить модуль `keyword` и воспользоваться командой\n", "> `keyword.kwlist`." ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "collapsed": false, "jupyter": { "outputs_hidden": false } }, "outputs": [], "source": [ "import keyword\n", "print(\"Python keywords: \" , keyword.kwlist)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "> \n", "> Проверить является или нет идентификатор ключевым словом можно так:" ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "collapsed": false, "jupyter": { "outputs_hidden": false } }, "outputs": [], "source": [ "keyword.iskeyword( \"try\" )" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ ">" ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "collapsed": false, "jupyter": { "outputs_hidden": false } }, "outputs": [], "source": [ "keyword.iskeyword( \"b\" )" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "> **Об использовании символа подчеркивания в именах переменных.**\n", ">\n", "> Не должны использоваться имена, начинающиеся и заканчивающиеся двумя\n", "> символами подчеркивания (такие как `__lt__`). В языке \n", "> Python определено множество различных специальных методов и переменных\n", "> с такими именами (и в случае специальных методов мы можем заменять их,\n", "> то есть создать свои версии этих методов), но мы не должны вводить\n", "> новые имена такого рода.\n", "> \n", "> Символ подчеркивания сам по себе может использоваться в качестве\n", "> идентификатора; внутри интерактивной оболочки интерпретатора или\n", "> в командной оболочке Python в переменной с именем `_` сохраняется\n", "> результат последнего вычисленного выражения. Во время выполнения\n", "> обычной программы идентификатор `_` отсутствует, если мы явно не\n", "> определяем его в своем программном коде. Некоторые программисты \n", "> любят использовать `_` в качестве идентификатора переменной цикла\n", "> в циклах `for` ... `in`, когда не требуется обращаться к элементам, по\n", "> которым выполняются итерации. Например:" ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "collapsed": false, "jupyter": { "outputs_hidden": false } }, "outputs": [], "source": [ "for _ in (0, 1, 2, 3, 4, 5):\n", " print(\"Hello\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Для того, чтобы посмотреть на объект с каким идентификатором ссылается данная\n", "переменная, можно использовать функцию `id()`." ] }, { "cell_type": "code", "execution_count": 7, "metadata": { "collapsed": false, "jupyter": { "outputs_hidden": false } }, "outputs": [], "source": [ "a = 4\n", "b = 5\n", "id (a)" ] }, { "cell_type": "code", "execution_count": 8, "metadata": { "collapsed": false, "jupyter": { "outputs_hidden": false } }, "outputs": [], "source": [ "id (b)" ] }, { "cell_type": "code", "execution_count": 9, "metadata": { "collapsed": false, "jupyter": { "outputs_hidden": false } }, "outputs": [], "source": [ "a = b\n", "id (a)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Как видно из примера, идентификатор – это некоторое целочисленное значение,\n", "посредством которого уникально адресуется объект. Изначально переменная a\n", "ссылается на объект `4` с идентификатором `1829984576`, переменная `b`\n", "– на объект с `id = 1829984592`. После выполнения операции\n", "присваивания `a = b`, переменная a стала ссылаться на тот же объект,\n", "что и `b`.\n", "\n", "\n", "\n", "![](fig-datatype/refs.png)\n", "\n", "\n", "Тип переменной можно определить с помощью функции `type()`. Пример\n", "использования приведен ниже." ] }, { "cell_type": "code", "execution_count": 10, "metadata": { "collapsed": false, "jupyter": { "outputs_hidden": false } }, "outputs": [], "source": [ "a = 10\n", "b = \"hello\"\n", "c = ( 1 , 2 )\n", "type (a)" ] }, { "cell_type": "code", "execution_count": 11, "metadata": { "collapsed": false, "jupyter": { "outputs_hidden": false } }, "outputs": [], "source": [ "type (b)" ] }, { "cell_type": "code", "execution_count": 12, "metadata": { "collapsed": false, "jupyter": { "outputs_hidden": false } }, "outputs": [], "source": [ "type (c)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Изменяемые и неизменяемые типы данных\n", "
\n", "\n", "В Python существуют изменяемые и неизменяемые типы.\n", "\n", "К неизменяемым (`immutable`) типам относятся:\n", "* целые числа (`int`);\n", "\n", "* числа с плавающей точкой (`float`);\n", "\n", "* комплексные числа (`complex`);\n", "\n", "* логические переменные (`bool`);\n", "\n", "* кортежи (`tuple`);\n", "\n", "* строки (`str`);\n", "\n", "* неизменяемые множества (`frozen set`).\n", "\n", "К изменяемым ( mutable ) типам относятся\n", "* списки (`list`);\n", "\n", "* множества (`set`);\n", "\n", "* словари (`dict`).\n", "\n", "Как уже было сказано ранее, при создании переменной, вначале создается объект,\n", "который имеет уникальный идентификатор, тип и значение, после этого переменная\n", "может ссылаться на созданный объект.\n", "\n", "Неизменяемость типа данных означает, что созданный объект больше не\n", "изменяется. Например, если мы объявим переменную `k = 15`, то будет создан объект\n", "со значением `15`, типа `int` и идентификатором, который можно узнать с помощью\n", "функции `id()`." ] }, { "cell_type": "code", "execution_count": 13, "metadata": { "collapsed": false, "jupyter": { "outputs_hidden": false } }, "outputs": [], "source": [ "k = 15\n", "id (k)" ] }, { "cell_type": "code", "execution_count": 14, "metadata": { "collapsed": false, "jupyter": { "outputs_hidden": false } }, "outputs": [], "source": [ "type (k)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Объект с `id = 1672501744` будет иметь значение `15` и изменить его уже нельзя.\n", "Если тип данных изменяемый, то можно менять значение объекта.\n", "\n", "Например, создадим список `[1, 2]`, а потом заменим второй элемент на\n", "`3`." ] }, { "cell_type": "code", "execution_count": 15, "metadata": { "collapsed": false, "jupyter": { "outputs_hidden": false } }, "outputs": [], "source": [ "a = [1 ,2]\n", "id (a)" ] }, { "cell_type": "code", "execution_count": 16, "metadata": { "collapsed": false, "jupyter": { "outputs_hidden": false } }, "outputs": [], "source": [ "a[1] = 3\n", "a" ] }, { "cell_type": "code", "execution_count": 17, "metadata": { "collapsed": false, "jupyter": { "outputs_hidden": false } }, "outputs": [], "source": [ "id(a)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Как видно, объект на который ссылается переменная `a`, был изменен. Это можно\n", "проиллюстрировать следующим рисунком.\n", "\n", "\n", "\n", "![](fig-datatype/mute.png)\n", "\n", "\n", "В рассмотренном случае, в качестве данных списка, выступают не объекты, а\n", "отношения между объектами. Т.е. в переменной a хранятся ссылки на объекты\n", "содержащие числа `1` и `3`, а не непосредственно сами эти числа.\n", "\n", "\n", "\n", "\n", "" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Целочисленные типы\n", "
\n", "\n", "В языке Python имеется два целочисленных типа, `int` и `bool`. И целые\n", "числа, и логические значения являются неизменяемыми объектами,\n", "но благодаря присутствию в языке Python комбинированных операторов\n", "присваивания эта особенность практически незаметна. В логических\n", "выражениях число `0` и значение `False` представляют `False`, а любое\n", "другое целое число и значение `True` представляют `True`. В числовых \n", "выражениях значение `True` представляет `1`, а `False` – `0`. Это означает,\n", "что можно записывать весьма странные выражения, например, выражение `i\n", "+= True` увеличит значение `i` на единицу. Естественно, более\n", "правильным будет записывать подобные выражения как `i += 1`. \n", "\n", "Размер целого числа ограничивается только объемом памяти компьютера,\n", "поэтому легко можно создать и обрабатывать целое число, состоящее из\n", "тысяч цифр, правда, скорость работы с такими числами существенно\n", "медленнее, чем с числами, которые соответствуют машинному\n", "представлению.\n", "\n", "Литералы целых чисел по умолчанию записываются в десятичной сис-\n", "теме счисления, но при желании можно использовать другие системы\n", "счисления:" ] }, { "cell_type": "code", "execution_count": 18, "metadata": { "collapsed": false, "jupyter": { "outputs_hidden": false } }, "outputs": [], "source": [ "14600926" ] }, { "cell_type": "code", "execution_count": 19, "metadata": { "collapsed": false, "jupyter": { "outputs_hidden": false } }, "outputs": [], "source": [ "0b110111101100101011011110" ] }, { "cell_type": "code", "execution_count": 20, "metadata": { "collapsed": false, "jupyter": { "outputs_hidden": false } }, "outputs": [], "source": [ "0o67545336" ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "collapsed": false, "jupyter": { "outputs_hidden": false } }, "outputs": [ { "data": { "text/plain": [ "14600926" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "0xDECADE" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Двоичные числа записываются с префиксом `0b`, восьмеричные – в\n", "префиксом `0o` и шестнадцатеричные – с префиксом `0x`. В префиксах\n", "допускается использовать символы верхнего регистра.\n", "\n", "При работе с целыми числами могут использоваться обычные\n", "математические функции и операторы, как показано в\n", "табл. [1](#datatype:tbl:1). Для арифметических операций `+`, `-`, `/`,\n", "`//`, `%` и `**` имеются соответствующие комбинированные операторы\n", "присваивания: `+=`, `-=`, `/=`, `//=`, `%=` и `**=`, где выражение\n", "`x op= y` является эквивалентом выражения `x = x op y`." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Таблица 1 : Арифметические операторы и функции\n", "
\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "
Синтаксис Описание
x + y Складывает число x и число y
x - y Вычитает число y из числа x
x * y Умножает x на y
x / y Делит x на y – результатом всегда является значение типа float (или complex, если x или y является комплексным числом)
x // y Делит x на y, при этом усекает дробную часть, поэтому результатом всегда является значение типа int; смотрите также функцию round()
x % y Возвращает модуль (остаток) от деления x на y
x**y Возводит x в степень y; смотрите также функцию pow()
-x Изменяет знак числа x, если оно не является нулем, если ноль – ничего не происходит
+x Ничего не делает иногда используется для повышения удобочитаемости программного кода
abs(x) Возвращает абсолютное значение x
divmod(x, y) Возвращает частное и остаток деления x на y в виде кортежа двух значений типа int
pow(x, y) Возводит x в степень y; то же самое что и оператор **
pow(x, y, z) Более быстрая альтернатива выражению (x ** y) % z
round(x, n) Возвращает значение типа int, соответствующее значению x типа float, округленному до ближайшего целого числа (или значение типа float, округленное до $n$-го знака после запятой, если задан аргумент n)
" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Объекты могут создаваться путем присваивания литералов переменным,\n", "например, `x = 17`, или обращением к имени соответствующего типа как к\n", "функции, например, `x = int(17)`. Создание объекта посредством\n", "использования его типа может быть выполнено одним из трех способов:\n", "\n", "* вызов типа данных без аргументов. В этом случае объект приобретает значение по умолчанию, например, выражение `x = int()` создаст целое число `0`. Любые встроенные типы могут вызываться без аргументов.\n", "\n", "* тип вызывается с единственным аргументом. Если указан аргумент соответствующего типа, будет создана поверхностная копия оригинального объекта. Если задан аргумент другого типа, будет предпринята попытка выполнить преобразование. Такой способ использования описывается в табл. [2](#datatype:tbl:2)\n", "\n", "* передается два или более аргументов; не все типы поддерживают такую возможность, а для тех типов, что поддерживают ее, типы аргументов и их назначение отличаются. В случае типа `int` допускается передавать два аргумента, где первый аргумент – это строка с представлением целого числа, а второй аргумент – число основания системы счисления. Например, вызов `int(\"A4\", 16)` создаст десятичное значение `164`." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Таблица 2 : Функции преобразования целых чисел
\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "
Синтаксис Описание
bin(i) Возвращает двоичное представление целого числа i в виде строки, например, bin(1980) == '0b11110111100'
hex(i) Возвращает шестнадцатеричное представление целого числа i в виде строки, например, hex(1980) == '0x7bc'
int(x) Преобразует объект x в целое число; в случае ошибки во время преобразования возбуждает исключение ValueError, а если тип объекта x не поддерживает преобразование в целое число возбуждает исключение TypeError. Если x является числом с плавающей точкой, оно преобразуется в целое число путем усечения дробной части.
int(s, base) Преобразует строку s в целое число; в случае ошибки возбуждает исключение ValueError. Если задан необязательный аргумент base, он должен быть целым числом в диапазоне от 2 до 36 включительно.
oct(i) Возвращает восьмеричное представление целого числа i в виде строки, например, oct(1980) == '0o3674'
" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "В табл. [3](#datatype:tbl:3) перечислены битовые операторы. Все битовые операторы\n", "(`|`, `^`, `&`, `<<` и `>>`) имеют соответствующие комбинированные операторы\n", "присваивания (`|=`, `^=`, `&=`, `<<=` и `>>=`), где выражение `i op= j` является\n", "логическим эквивалентом выражения `i = i op j` в случае, когда обращение\n", "к значению `i` не имеет побочных эффектов." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Таблица 3 : Функции преобразования целых чисел
\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "
Синтаксис Описание
i | j Битовая операция OR (ИЛИ) над целыми числами i и j; отрицательные числа представляются как двоичное дополнение
i ^ j Битовая операция XOR (исключающее ИЛИ) над целыми числами i и j
i & j Битовая операция AND (И) над целыми числами i и j
i << j Сдвигает значение i влево на j битов аналогично операции i * (2 ** j) без проверки на переполнение
i >> j Сдвигает значение i вправо на j битов аналогично операции i // (2 ** j) без проверки на переполнение
\\~i Инвертирует биты числа i
" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Логические значения\n", "
\n", "\n", "Существует два встроенных логических объекта: `True` и `False`. Как\n", "и все остальные типы данных в языке Python (встроенные, библиотечные\n", "или ваши собственные), тип данных `bool` может вызываться как \n", "функция – при вызове без аргументов возвращается значение `False`,\n", "при вызове с аргументом типа `bool` возвращается копия аргумента,\n", "а при вызове с любым другим аргументом предпринимается попытка\n", "преобразовать указанный объект в тип `bool`. Все встроенные типы\n", "данных и типы данных из стандартной библиотеки могут быть\n", "преобразованы в тип `bool`, а добавить поддержку такого преобразования в\n", "свои собственные типы данных не представляет никакой сложности. Ниже\n", "приводится пара присваиваний логических значений и пара логических\n", "выражений:" ] }, { "cell_type": "code", "execution_count": 22, "metadata": { "collapsed": false, "jupyter": { "outputs_hidden": false } }, "outputs": [], "source": [ "t = True" ] }, { "cell_type": "code", "execution_count": 23, "metadata": { "collapsed": false, "jupyter": { "outputs_hidden": false } }, "outputs": [], "source": [ "f = False" ] }, { "cell_type": "code", "execution_count": 24, "metadata": { "collapsed": false, "jupyter": { "outputs_hidden": false } }, "outputs": [], "source": [ "t and f" ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "collapsed": false, "jupyter": { "outputs_hidden": false } }, "outputs": [ { "ename": "NameError", "evalue": "name 't' is not defined", "output_type": "error", "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mNameError\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[0mt\u001b[0m \u001b[0;32mand\u001b[0m \u001b[0;32mTrue\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", "\u001b[0;31mNameError\u001b[0m: name 't' is not defined" ] } ], "source": [ "t and True" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "в языке Python имеется три логических оператора: `and`, `or` и\n", "`not`. Выражения с участием операторов `and` и `or` вычисляются в\n", "соответствии с логикой сокращенных вычислений (*short-circuit logic*),\n", "и возвращается операнд, определяющий значение всего\n", "выражения, тогда как результатом оператора `not` всегда\n", "является либо `True`, либо `False`.\n", "\n", "\n", "\n", "\n", "\n", "" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Типы чисел с плавающей точкой\n", "
\n", "\n", "Язык Python предоставляет три типа значений с плавающей точкой:\n", "встроенные типы `float` и `complex` и тип `decimal.Decimal` в\n", "стандартной библиотеке. Все три типа данных относятся к категории\n", "неизменяемых. Тип `float` представляет числа с плавающей точкой\n", "двойной точности, диапазон значений которых зависит от компилятора\n", "языка C (или C\\# или Java), применявшегося для компиляции интерпретатора\n", "Python. Числа этого типа имеют ограниченную точность и не могут\n", "надежно сравниваться на равенство значений. Числа типа `float`\n", "записываются с десятичной точкой или в экспоненциальной форме записи, \n", "например, `0.0`, `4.`, `5.7`, `-2.5`, `-2e9`, `8.9e-4`.\n", "\n", "В машинном представлении числа с плавающей точкой хранятся как\n", "двоичные числа. Это означает, что одни дробные значения могут быть\n", "представлены точно (такие как `0.5`), а другие – только приблизительно\n", "(такие как `0.1` и `0.2`). Кроме того, для представления используется\n", "фиксированное число битов, поэтому существует ограничение на\n", "количество цифр в представлении таких чисел. Ниже приводится\n", "поясняющий пример:" ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "collapsed": false, "jupyter": { "outputs_hidden": false } }, "outputs": [ { "data": { "text/plain": [ "(0.0, 5.4, -2.5, 0.00089)" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "0.0, 5.4, -2.5, 8.9e-4" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Проблема потери точности – это не проблема, свойственная только\n", "языку Python; все языки программирования обнаруживают проблему\n", "с точным представлением чисел с плавающей точкой.\n", "\n", "Если действительно необходимо обеспечить высокую точность,\n", "можно использовать числа типа `decimal.Decimal`. Эти числа\n", "обеспечивают уровень точности, который вы укажете (по умолчанию 28\n", "знаков после запятой), и могут точно представлять периодические числа,\n", "такие как $0.1$ , но скорость работы с такими числами существенно\n", "ниже, чем с обычными числами типа `float`. Вследствие высокой точности\n", "числа типа `decimal.Decimal` прекрасно подходят для производства\n", "финансовых вычислений.\n", "\n", "Смешанная арифметика поддерживается таким образом, что результатом\n", "выражения с участием чисел типов `int` и `float` является число типа\n", "`float`, а с участием типов `float` и `complex` результатом является\n", "число типа `complex`. Поскольку числа типа `decimal.Decimal` имеют\n", "фиксированную точность, они могут участвовать в выражениях только с\n", "другими числами `decimal.Decimal` и с числами типа `int`; результатом \n", "таких выражений является число `decimal.Decimal`. В случае попытки\n", "выполнить операцию над несовместимыми типами возбуждается исключение\n", "`TypeError`." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Числа с плавающей точкой\n", "
\n", "\n", "Все числовые операторы и функции, представленные в\n", "табл. [Таблица 1 : Арифметические операторы и функции](#datatype:tbl:1), могут применяться к числам типа float,\n", "включая комбинированные операторы присваивания. Тип данных float может\n", "вызываться как функция – без аргументов возвращается число `0.0`, с\n", "аргументом типа float возвращается копия аргумента, а с аргументом\n", "любого другого типа предпринимается попытка выполнить преобразование\n", "указанного объекта в тип float. При преобразовании строки \n", "аргумент может содержать либо простую форму записи числа с десятичной\n", "точкой, либо экспоненциальное представление числа. При выполнении\n", "операций с числами типа float может возникнуть ситуация, \n", "когда в результате получается значение `NaN` (*not a number* – не\n", "число) или «бесконечность». К сожалению, поведение интерпретатора в\n", "таких ситуациях может отличаться в разных реализациях и зависит от \n", "математической библиотеки системы.\n", "\n", "Ниже приводится пример простой функции, выполняющей сравнение\n", "чисел типа float на равенство в пределах машинной точности:" ] }, { "cell_type": "code", "execution_count": 27, "metadata": { "collapsed": false, "jupyter": { "outputs_hidden": false } }, "outputs": [], "source": [ "def equal_float(a, b):\n", " return abs(a - b) <= sys.float_info.epsilon" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Чтобы воспользоваться этой функцией, необходимо импортировать\n", "модуль `sys`. Объект `sys.float_info` имеет множество атрибутов. Так,\n", "`sys.float_info.epsilon` хранит минимально возможную разницу между\n", "двумя числами с плавающей точкой. На одной из 32-разрядных машин\n", "автора книги это число чуть больше $0.000 000 000 000 000 2$.\n", "Тип `float` в языке Python обеспечивает надежную точность до 17\n", "значащих цифр.\n", "\n", "В дополнение к встроенным функциональным возможностям работы\n", "с числами типа `float` модуль `math` предоставляет множество функций,\n", "которые приводятся в табл. [datatype:tbl:4](#datatype:tbl:4). Ниже приводятся\n", "несколько фрагментов программного кода, демонстрирующих, как можно\n", "использовать функциональные возможности модуля:" ] }, { "cell_type": "code", "execution_count": 28, "metadata": { "collapsed": false, "jupyter": { "outputs_hidden": false } }, "outputs": [], "source": [ "import math\n", "math.pi * (5 ** 2)" ] }, { "cell_type": "code", "execution_count": 29, "metadata": { "collapsed": false, "jupyter": { "outputs_hidden": false } }, "outputs": [], "source": [ "math.hypot(5, 12)" ] }, { "cell_type": "code", "execution_count": 30, "metadata": { "collapsed": false, "jupyter": { "outputs_hidden": false } }, "outputs": [], "source": [ "math.modf(13.732)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Таблица 4 : Функции и константы модуля `math`
\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "
Синтаксис Описание
math.acos(x) Возвращает арккосинус x в радианах
math.acosh(x) Возвращает гиперболический арккосинус x в радианах
math.asin(x) Возвращает арксинус x в радианах
math.asinh(x) Возвращает гиперболический арксинус x в радианах
math.atan(x) Возвращает арктангенс x в радианах
math.atan2(y x) Возвращает арктангенс y/x в радианах
math.atanh(x) Возвращает гиперболический арктангенс x в радианах
math.ceil(x) Возвращает $ | x | $, то есть наименьшее целое число типа int, большее и равное x, например, math.ceil(5.4) == 6
math.copysign(x y) Возвращает x со знаком числа y
math.cos(x) Возвращает косинус x в радианах
math.cosh(x) Возвращает гиперболический косинус x в радианах
math.degrees(r) Преобразует число r типа float из радианов в градусы
math.e Константа $e$, примерно равная значению $2.7182818284590451$
math.exp(x) Возвращает $e^x$, то есть math.e ** x
math.fabs(x) Возвращает $ | x | $, то есть абсолютное значение x в виде числа типа float
math.factorial(x) Возвращает $x!$
math.floor(x) Возвращает $ | x | $, то есть наименьшее целое число типа int, меньшее и равное x, например, math.floor(5.4) == 5
math.fmod(x y) Выполняет деление по модулю (возвращает остаток) числа x на число y; дает более точный результат, чем оператор %, применительно к числам типа float
math.frexp(x) Возвращает кортеж из двух элементов с мантиссой (в виде числа типа float) и экспонентой (в виде числа типа int)
math.fsum(i) Возвращает сумму значений в итерируемом объекте i в виде числа типа float
math.hypot(x y) Возвращает $\\sqrt{x^2 + y^2}$
math.isinf(x) Возвращает True, если значение x типа float является бесконечностью ($\\pm \\infty$)
math.isnan(x) Возвращает True, если значение x типа float не является числом
math.ldexp(m e) Возвращает $m\\times 2^e$ – операция обратная math.frexp()
math.log(x b) Возвращает $\\log_b x$, аргумент b является необязательным и по умолчанию имеет значение math.e
math.log10(x) Возвращает $log_{10} x$
math.log1p(x) Возвращает $log_e (1+x)$; дает точные значения даже когда значение x близко к 0
math.modf(x) Возвращает дробную и целую часть числа x в виде двух значений типа float
math.pi Константа $\\pi$, примерно равная $3.1415926535897931$
math.pow(x y) Возвращает $x^y$ в виде числа типа float
math.radians(d) Преобразует число d типа float из градусов в радианы
math.sin(x) Возвращает синус x в радианах
math.sinh(x) Возвращает гиперболический синус x в радианах
math.sqrt(x) Возвращает $\\sqrt{x}$
math.tan(x) Возвращает тангенс x в радианах
math.tanh(x) Возвращает гиперболический тангенс x в радианах
math.trunc(x) Возвращает целую часть числа x в виде значения типа int; то же самое что и int(x)
" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "## Комплексные числа\n", "
\n", "\n", "Тип данных `complex` относится к категории неизменяемых и хранит пару\n", "значений типа `float`, одно из которых представляет действительную\n", "часть комплексного числа, а другое – мнимую. Литералы комплексных\n", "чисел записываются как действительная и мнимая части, объединенные\n", "знаком `+` или `-`, а за мнимой частью числа следует символ `j`.\n", "Вот примеры нескольких комплексных чисел: `3.5+2j`, `0.5j`, `4+0j`,\n", "`-1 - 3.7j`. Обратите внимание, что если действительная часть числа\n", "равна `0`, ее можно вообще опустить.\n", "\n", "Отдельные части комплексного числа доступны в виде атрибутов `real`\n", "и `imag`. Например:" ] }, { "cell_type": "code", "execution_count": 31, "metadata": { "collapsed": false, "jupyter": { "outputs_hidden": false } }, "outputs": [], "source": [ "z = -89.5+2.125j\n", "z.real, z.imag" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "За исключением `//`, `%`, `divmod()` и версии `pow()` с тремя\n", "аргументами все остальные арифметические операторы и функции,\n", "перечисленные в табл. [Таблица 1 : Арифметические операторы и функции](#datatype:tbl:1) могут использоваться для\n", "работы с комплексными числами, так же как и соответствующие\n", "комбинированные операторы присваивания. Кроме того, значения типа\n", "`complex` имеют метод `conjugate()`, который изменяет знак мнимой\n", "части. Например:" ] }, { "cell_type": "code", "execution_count": 32, "metadata": { "collapsed": false, "jupyter": { "outputs_hidden": false } }, "outputs": [], "source": [ "z.conjugate()" ] }, { "cell_type": "code", "execution_count": 33, "metadata": { "collapsed": false, "jupyter": { "outputs_hidden": false } }, "outputs": [], "source": [ "3-4j.conjugate()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Тип данных `complex` может вызываться как функция – без аргументов\n", "она вернет значение `0j`, с аргументом типа `complex` она вернет копию\n", "аргумента, а с аргументом любого другого типа она попытается\n", "преобразовать указанный объект в значение типа `complex`. При\n", "использовании для преобразования функция `complex()` принимает либо\n", "единственный строковый аргумент, либо одно или два значения типа\n", "`float`.\n", "\n", "Если ей передается единственное значение типа `float`, возвращается\n", "комплексное число с мнимой частью, равной `0j`.\n", "\n", "Функции в модуле `math` не работают с комплексными числами. Это\n", "сделано преднамеренно, чтобы гарантировать, что пользователи модуля \n", "`math` будут получать исключения вместо получения комплексных чисел в\n", "некоторых случаях.\n", "\n", "Если возникает необходимость использовать комплексные числа,\n", "можно воспользоваться модулем `cmath`, который содержит комплексные\n", "версии большинства тригонометрических и логарифмических функций,\n", "присутствующих в модуле math, плюс ряд функций, специально\n", "предназначенных для работы с комплексными числами, таких \n", "как `cmath.phase()`, `cmath.polar()` и `cmath.rect()`, а также\n", "константы `cmath.pi` и `cmath.e`, которые хранят те же самые значения\n", "типа `float`, что и родственные им константы в модуле `math`." ] }, { "cell_type": "code", "execution_count": 34, "metadata": { "collapsed": false, "jupyter": { "outputs_hidden": false } }, "outputs": [], "source": [ "import decimal\n", "a = decimal.Decimal(9876)\n", "b = decimal.Decimal(\"54321.012345678987654321\")\n", "a + b" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "\n", "\n", "\n", "# Строки\n", "
\n", "\n", "Строки в языке Python представлены неизменяемым типом данных `str`,\n", "который хранит последовательность символов Юникода. Тип данных `str`\n", "может вызываться как функция для создания строковых объектов – без\n", "аргументов возвращается пустая строка; с аргументом, который не\n", "является строкой, возвращается строковое представление аргумента; а в\n", "случае, когда аргумент является строкой, возвращается его\n", "копия. Функция `str()` может также использоваться как функция\n", "преобразования. В этом случае первый аргумент должен быть строкой или\n", "объектом, который можно преобразовать в строку, а, кроме того, функции\n", "может быть передано до двух необязательных строковых аргументов, один\n", "из которых определяет используемую кодировку, а второй определяет\n", "порядок обработки ошибок кодирования.\n", "\n", "Литералы строк создаются с использованием кавычек или апострофов, при\n", "этом важно, чтобы с обоих концов литерала использовались кавычки\n", "одного и того же типа. В дополнение к этому мы можем использовать\n", "строки в тройных кавычках, то есть строки, которые начинаются и\n", "заканчиваются тремя символами кавычки (либо тремя кавычками, либо\n", "тремя апострофами). Например:" ] }, { "cell_type": "code", "execution_count": 35, "metadata": { "collapsed": false, "jupyter": { "outputs_hidden": false } }, "outputs": [], "source": [ "text = \"\"\"Строки в тройных кавычках могут включать 'апострофы' и \"кавычки\"\n", "без лишних формальностей. Мы можем даже экранировать символ перевода строки \\,\n", "благодаря чему данная конкретная строка будет занимать всего две строки.\"\"\"" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Если нам потребуется использовать кавычки в строке, это можно сделать\n", "без лишних формальностей – при условии, что они отличаются от кавычек,\n", "ограничивающих строку; в противном случае символы кавычек или\n", "апострофов внутри строки следует экранировать:" ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "collapsed": false, "jupyter": { "outputs_hidden": false } }, "outputs": [], "source": [ "a = \"Здесь 'апострофы' можно не экранировать, а \\\"кавычки\\\" придется.\"\n", "b = 'Здесь \\'апострофы\\' придется экранировать, а \"кавычки\" не обязательно.'" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Таблица 5 : Функции и константы модуля `math`
\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "
Последовательность Значение
\\переводстроки Экранирует (то есть игнорирует) символ перевода строки
\\\\ Символ обратного слеша (\\)
\\' Апостроф (')
\\\" Кавычка (\")
\\a Символ ASCII «сигнал» (bell, BEL)
\\b Символ ASCII «забой» (backspace, BS)
\\f Символ ASCII «перевод формата» (formfeed, FF)
\\n Символ ASCII «перевод строки» (linefeed, LF)
\\N{название} Символ Юникода с заданным названием
\\ooo Символ с заданным восьмеричным кодом
\\r Символ ASCII «возврат каретки» (carriage return, CR)
\\t Символ ASCII «табуляция» (tab, TAB)
\\uhhhh Символ Юникода с указанным 16-битовым шестнадцатеричным значением
\\Uhhhhhhhh Символ Юникода с указанным 32-битовым шестнадцатеричным значением
\\v Символ ASCII «вертикальная табуляция» (vertical tab, VT)
\\xhh Символ с указанным 8-битовым шестнадцатеричным значением
\n", "\n", "\n", "Если потребуется записать длинный строковый литерал, занимающий\n", "две или более строк, но без использования тройных кавычек, то можно\n", "использовать один из приемов, показанных ниже:" ] }, { "cell_type": "code", "execution_count": 8, "metadata": { "collapsed": false, "jupyter": { "outputs_hidden": false } }, "outputs": [], "source": [ "t = \"Это не самый лучший способ объединения двух длинных строк, \" + \\\n", " \"потому что он основан на использовании неуклюжего экранирования\"\n", "s = (\"Это отличный способ объединить две длинные строки, \"\n", " \" потому что он основан на конкатенации строковых литералов.\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Получение срезов строк\n", "
\n", "\n", "Отдельные элементы последовательности, а, следовательно, и отдельные\n", "символы в строках, могут извлекаться с помощью оператора доступа к\n", "элементам (`[]`). В действительности этот оператор намного более\n", "универсальный и может использоваться для извлечения не только одного\n", "символа, но и целых комбинаций (подпоследовательностей) элементов или\n", "символов, когда этот оператор используется в контексте оператора\n", "извлечения среза.\n", "\n", "Для начала мы рассмотрим возможность извлечения отдельных\n", "символов. Нумерация позиций символов в строках начинается с 0 и\n", "продолжается до значений длины строки минус 1. Однако допускается\n", "использовать и отрицательные индексы – в этом случае отсчет начинается\n", "с последнего символа и ведется в обратном направлении к первому \n", "символу. На рис. [1](#datatype:strings:fig:1) показано, как нумеруются\n", "позиции символов в строке, если предположить, что было выполнено\n", "присваивание `s = \"Light ray\"`. \n", "\n", "\n", "\n", "
Рис. 1: Номера позиций символов в строке
\n", "\n", "![Номера позиций символов в строке](fig-datatype/strings_1.png)\n", "\n", "\n", "Отрицательные индексы удивительно удобны, особенно индекс `-1`,\n", "который всегда соответствует последнему символу строки. Попытка\n", "обращения к индексу, находящемуся за пределами строки (или к любому\n", "индексу в пустой строке), будет вызывать исключение `IndexError`.\n", "Оператор получения среза имеет три формы записи:" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "```Python\n", " seq[start]\n", " seq[start:end]\n", " seq[start:end:step]\n", "```" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Ссылка `seq` может представлять любую последовательность, такую как\n", "список, строку или кортеж. Значения `start`, `end` и `step` должны быть\n", "целыми числами (или переменными, хранящими целые числа). Первая форма\n", "— это запись оператора доступа к элементам: с ее помощью извлекается\n", "элемент последовательности с индексом `start`. Вторая форма записи\n", "извлекает подстроку, начиная с элемента с индексом `start` и заканчивая\n", "элементом с индексом `end`, *не включая* его.\n", "\n", "При использовании второй формы записи (с одним двоеточием) мы можем\n", "опустить любой из индексов. Если опустить начальный индекс, по\n", "умолчанию будет использоваться значение `0`. Если опустить конечный\n", "индекс, по умолчанию будет использоваться значение `len(seq)`. \n", "Это означает, что если опустить оба индекса, например, `s[:]`, это будет\n", "равносильно выражению `s[0:len(s)]`, и в результате будет извлечена,\n", "то есть скопирована, последовательность целиком.\n", "\n", "На рис. [2](#datatype:strings:fig:2) приводятся некоторые примеры\n", "извлечения срезов из строки `s`, которая получена в результате\n", "присваивания `s = \"The waxwork man\"`.\n", "\n", "\n", "\n", "
Рис 2: Извлечение срезов из последовательности
\n", "\n", "![Извлечение срезов из последовательности](fig-datatype/strings_2.png)\n", "\n", "\n", "Один из способов вставить подстроку в строку состоит в смешивании\n", "операторов извлечения среза и операторов конкатенации. Например:" ] }, { "cell_type": "code", "execution_count": 38, "metadata": { "collapsed": false, "jupyter": { "outputs_hidden": false } }, "outputs": [], "source": [ "s = s[:12] + \"wo\" + s[12:]" ] }, { "cell_type": "code", "execution_count": 39, "metadata": { "collapsed": false, "jupyter": { "outputs_hidden": false } }, "outputs": [], "source": [ "s" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Кроме того, поскольку текст «wo» присутствует в оригинальной строке,\n", "тот же самый эффект можно было бы получить путем присваивания значения\n", "выражения `s[:12] + s[7:9] + s[12:]`.\n", "\n", "Оператор конкатенации `+` и добавления подстроки `+=` не\n", "особенно эффективны, когда в операции участвует множество строк. Для\n", "объединения большого числа строк обычно лучше использовать метод\n", "`str.join()`, с которым мы познакомимся в следующем подразделе.\n", "\n", "Третья форма записи (с двумя двоеточиями) напоминает вторую форму, но\n", "в отличие от нее значение `step` определяет, с каким шагом следует\n", "извлекать символы. Как и при использовании второй формы записи, мы\n", "можем опустить любой из индексов. Если опустить начальный \n", "индекс, по умолчанию будет использоваться значение `0`, при условии,\n", "что задано неотрицательное значение step; в противном случае начальный\n", "индекс по умолчанию получит значение `-1`. Если опустить конечный\n", "индекс, по умолчанию будет использоваться значение `len(seq)`, \n", "при условии, что задано неотрицательное значение step; в противном\n", "случае конечный индекс по умолчанию получит значение индекса перед\n", "началом строки. Мы не можем опустить значение step, и оно не может\n", "быть равно нулю – если задание шага не требуется, то следует\n", "использовать вторую форму записи (с одним двоеточием), в которой шаг \n", "выбора элементов не указывается.\n", "\n", "На рис. [Извлечение разреженных срезов](#datatype:strings:fig:3) приводится пара примеров извлечения разреженных срезов из\n", "строки `s`, которая получена в результате присваивания\n", "`s = \"he ate camel food\"`.\n", "\n", "\n", "\n", "
\n", "\n", "![Извлечение разреженных срезов](fig-datatype/strings_3.png)\n", "\n", "\n", "Здесь мы использовали значения по умолчанию для начального и ко-\n", "нечного индексов, то есть извлечение среза s[:: – 2] начинается с по-\n", "следнего символа строки и извлекается каждый второй символ по на-\n", "правлению к началу строки. Аналогично извлечение среза s[::3] на-\n", "чинается с первого символа строки и извлекается каждый третий сим-\n", "вол по направлению к концу строки.\n", "Существует возможность комбинировать индексы с размером шага,\n", "как показано на рис. [Извлечение срезов из последовательности с определенным шагом](#datatype:strings:fig:4).\n", "\n", "\n", "\n", "
\n", "\n", "![Извлечение срезов из последовательности с определенным шагом](fig-datatype/strings_4.png)\n", "\n", "\n", "Операция извлечения элементов с определенным шагом часто применяется к\n", "последовательностям, отличным от строк, но один из ее вариантов часто\n", "применяется к строкам:" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Операторы и методы строк\n", "
\n", "\n", "Поскольку строки относятся к категории неизменяемых\n", "последовательностей, все функциональные возможности, применимые к\n", "неизменяемым последовательностям, могут использоваться и со\n", "строками. Сюда входят оператор проверки на вхождение `in`, оператор\n", "конкатенации `+`, оператор добавления в конец `+=`, оператор\n", "дублирования `*` и комбинированный оператор присваивания с\n", "дублированием `*=`. Применение всех этих операторов в контексте строк\n", "мы обсудим в этом подразделе, а также обсудим большинство строковых\n", "методов. В табл. 2.7 приводится перечень некоторых строковых методов.\n", "\n", "Так как строки являются последовательностями, они являются объектами,\n", "имеющими «размер», и поэтому мы можем вызывать функцию `len()`,\n", "передавая ей строки в качестве аргумента. Возвращаемая функцией длина\n", "представляет собой количество символов в строке (ноль – для пустых\n", "строк).\n", "\n", "Мы уже знаем, что перегруженная версия оператора `+` для строк\n", "выполняет операцию конкатенации. В случаях, когда требуется объединить\n", "множество строк, лучше использовать метод `str.join()`. Метод \n", "принимает в качестве аргумента последовательность (то есть список\n", "или кортеж строк) и объединяет их в единую строку, вставляя между\n", "ними строку, относительно которой был вызван метод. Например:" ] }, { "cell_type": "code", "execution_count": 40, "metadata": { "collapsed": false, "jupyter": { "outputs_hidden": false } }, "outputs": [], "source": [ "treatises = [\"Arithmetica\", \"Conics\", \"Elements\"]\n", "\" \".join(treatises)" ] }, { "cell_type": "code", "execution_count": 41, "metadata": { "collapsed": false, "jupyter": { "outputs_hidden": false } }, "outputs": [], "source": [ "\"-<>-\".join(treatises)" ] }, { "cell_type": "code", "execution_count": 42, "metadata": { "collapsed": false, "jupyter": { "outputs_hidden": false } }, "outputs": [], "source": [ "\"\".join(treatises)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Метод `str.join()` может также использоваться в комбинации со\n", "встроенной функцией `reversed()`, которая переворачивает строку –\n", "например, `\"\".join(reversed(s))`, хотя тот же результат может быть\n", "получен более кратким оператором извлечения разреженного среза –\n", "например, `s[:: – 1]`.\n", "\n", "Оператор `*` обеспечивает возможность дублирования строки:" ] }, { "cell_type": "code", "execution_count": 43, "metadata": { "collapsed": false, "jupyter": { "outputs_hidden": false } }, "outputs": [], "source": [ "s = \"=\" * 5\n", "print(s)" ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.Это отличный способ объединить две длинные строки, потому что он основан на конкатенации строковых литералов.\n" ] } ], "source": [ "s *= 10\n", "print(s)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Как показано в примере, мы можем также использовать комбинированный\n", "оператор присваивания с дублированием. " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Форматирование строк с помощью метода `str.format()`\n", "
\n", "\n", "Метод `str.format()` представляет собой очень мощное и гибкое средство\n", "создания строк. Использование метода `str.format()` в простых случаях\n", "не вызывает сложностей, но для более сложного форматирования нам\n", "необходимо изучить синтаксис форматирования.\n", "\n", "Метод `str.format()` возвращает новую строку, замещая поля в\n", "контекстной строке соответствующими аргументами. Например:" ] }, { "cell_type": "code", "execution_count": 45, "metadata": {}, "outputs": [], "source": [ "\"The novel '{0}' was published in {1}\".format(\"Hard Times\", 1854)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Каждое замещаемое поле идентифицируется именем поля в фигурных\n", "скобках. Если в качестве имени поля используется целое число, оно\n", "определяет порядковый номер аргумента, переданного методу\n", "`str.format()`. Поэтому в данном случае поле с именем `0` было замещено\n", "первым аргументом, а поле с именем `1` – вторым аргументом. \n", "\n", "Если бы нам потребовалось включить фигурные скобки в строку формата,\n", "мы могли бы сделать это, дублируя их, как показано ниже:" ] }, { "cell_type": "code", "execution_count": 46, "metadata": { "collapsed": false, "jupyter": { "outputs_hidden": false } }, "outputs": [], "source": [ "\"{{{0}}} {1} ;-}}\".format(\"I'm in braces\", \"I'm not\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Если попытаться объединить строку и число, интерпретатор Python\n", "совершенно справедливо возбудит исключение `TypeError`. Но это легко\n", "можно сделать с помощью метода `str.format()`:" ] }, { "cell_type": "code", "execution_count": 47, "metadata": { "collapsed": false, "jupyter": { "outputs_hidden": false } }, "outputs": [], "source": [ "\"{0}{1}\".format(\"The amount due is $\", 200)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "С помощью `str.format()` мы также легко можем объединять строки\n", "(хотя для этой цели лучше подходит метод `str.join()`):" ] }, { "cell_type": "code", "execution_count": 12, "metadata": { "collapsed": false, "jupyter": { "outputs_hidden": false } }, "outputs": [ { "data": { "text/plain": [ "'The three tops'" ] }, "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ "x = \"three\"\n", "s =\"{0} {1} {2}\"\n", "s = s.format(\"The\", x, \"tops\")\n", "s" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "В следующем разделе мы рассмотрим применение функции `str.format()`." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "\n", "\n", "\n", "# Примеры\n", "
" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Печать символов Юникода\n", "
\n", "\n", "Рассмотрим небольшой, но достаточно поучительный пример использования\n", "метода `str.format()`, в котором мы увидим применение спецификаторов\n", "формата в реальном контексте. Программа, состоящая всего из 25 строк\n", "выполняемого кода, находится в файле\n", "[print_unicode.py](src-datatype/print_unicode.py). Она импортирует\n", "два модуля, `sys` и `unicodedata` и определяет одну функцию –\n", "`print_unicode_table()`. Рассмотрение примера мы начнем\n", "с запуска программы, чтобы увидеть, что она делает; затем мы\n", "рассмотрим программный код в конце программы, где выполняется вся\n", "фактическая работа; и в заключение рассмотрим функцию, определяемую в\n", "программе." ] }, { "cell_type": "code", "execution_count": 49, "metadata": { "collapsed": false, "jupyter": { "outputs_hidden": false } }, "outputs": [], "source": [ "%run src-datatype/print_unnicode.py Spoked" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "При запуске без аргументов программа выводит таблицу всех символов\n", "Юникода, начиная с пробела и до символа с наибольшим возможным\n", "кодом. При запуске с аргументом, как показано в примере, выводятся \n", "только те строки таблицы, где в названии символов Юникода содержится\n", "значение строки-аргумента, переведенной в нижний регистр.\n", "\n", "Разберем исходный код программы:" ] }, { "cell_type": "code", "execution_count": 50, "metadata": { "collapsed": false, "jupyter": { "outputs_hidden": false } }, "outputs": [], "source": [ "# Start main script\n", "word = None\n", "\n", "if len(sys.argv) > 1:\n", " if sys.argv[1] in (\"-h\", \"--help\"):\n", " print(\"usage: {0} [string]\".format(sys.argv[0]))\n", " word = 0\n", " else:\n", " word = sys.argv[1].lower()\n", "\n", "if word != 0:\n", " print_unicode_table(word)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "После инструкций импортирования и определения функции\n", "`print_unicode_table()` выполнение достигает программного кода,\n", "показанного выше. Сначала предположим, что пользователь не указал в\n", "командной строке искомое слово. Если аргумент командной строки\n", "присутствует и это `-h` или `--help`, программа выводит информацию о\n", "порядке использования и устанавливает флаг `word` в значение `0`, указывая\n", "тем самым, что работа завершена. В противном случае в переменную `word`\n", "записывается копия аргумента, введенного пользователем, с\n", "преобразованием всех символов в нижний регистр. Если значение `word` не\n", "равно `0`, программа выводит таблицу.\n", "\n", "При выводе информации о порядке использования применяется спецификатор\n", "формата, который представляет собой простое имя формата, в данном\n", "случае – порядковый номер позиционного аргумента. Мы могли бы записать\n", "эту строку, как показано ниже:" ] }, { "cell_type": "code", "execution_count": 51, "metadata": { "collapsed": false, "jupyter": { "outputs_hidden": false } }, "outputs": [], "source": [ "print(\"usage: {0[0]} [string]\".format(sys.argv))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "При таком подходе первый символ `0` соответствует порядковому номеру\n", "позиционного аргумента, а `[0]` — это индекс элемента внутри\n", "аргумента, и такой прием сработает, потому что `sys.argv` является\n", "списком." ] }, { "cell_type": "code", "execution_count": 52, "metadata": { "collapsed": false, "jupyter": { "outputs_hidden": false } }, "outputs": [], "source": [ "def print_unicode_table(word):\n", " print(\"decimal hex chr {0:^40}\".format(\"name\"))\n", " print(\"------- ----- --- {0:-<40}\".format(\"\"))\n", "\n", " code = ord(\" \")\n", " end = sys.maxunicode\n", "\n", " while code < end:\n", " c = chr(code)\n", " name = unicodedata.name(c, \"*** unknown ***\")\n", " if word is None or word in name.lower():\n", " print(\"{0:7} {0:5X} {0:^3c} {1}\".format(code, name.title()))\n", " code += 1" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Первый вызов `str.format()` выводит текст `\"name\"`, отцентрированный в\n", "поле вывода, шириной 40 символов, а второй вызов выводит пустую строку\n", "в поле шириной 40 символов, используя символ `-` в качестве\n", "символа-заполнителя, с выравниванием по левому краю. \n", "\n", "Как вариант, вторую строку функции можно было записать, как показано ниже:" ] }, { "cell_type": "code", "execution_count": 53, "metadata": { "collapsed": false, "jupyter": { "outputs_hidden": false } }, "outputs": [], "source": [ "print(\"------- ----- --- {0}\".format(\"-\" * 40))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Здесь мы использовали оператор дублирования строки (`*`), чтобы\n", "создать необходимую строку, и просто вставили ее в строку формата.\n", "\n", "Текущий код символа Юникода сохраняется в переменной `code`, которая\n", "инициализируется кодом пробела (`0x20`). В переменную end записывается\n", "максимально возможный код символа Юникода, который может принимать\n", "разные значения в зависимости от того, какая из кодировок\n", "использовалась при компиляции Python.\n", "\n", "Внутри цикла `while` с помощью функции `chr()` мы получаем символ\n", "Юникода, соответствующий числовому коду. Функция `unicodedata.name()`\n", "возвращает название заданного символа Юникода, во втором\n", "необязательном аргументе передается имя, которое будет использовано в\n", "случае, когда имя символа не определено. \n", "\n", "Если пользователь не указывает аргумент командной строки (`word is None`)\n", "или аргумент был указан и он входит в состав копии имени символа\n", "Юникода, в которой все символы приведены к нижнему регистру, то\n", "выводится соответствующая строка таблицы. \n", "\n", "Мы передаем переменную `code` методу `str.format()` один раз, но в\n", "строке формата она используется трижды. Первый раз – при выводе\n", "значения `code` как целого числа в поле с шириной 7 символов (по\n", "умолчанию в качестве символа-заполнителя используется пробел, поэтому\n", "нет необходимости явно указывать его). Второй раз – при выводе\n", "значения `code` как целого числа в шестнадцатеричном формате символами\n", "верхнего регистра в поле шириной 5 символов. И третий раз – при выводе \n", "символа Юникода, соответствующего значению code, с помощью\n", "спецификатора формата `c`, отцентрированного в поле с минимальной \n", "шириной 3 символа. Обратите внимание, что нам не потребовалось\n", "указывать тип `d` в первом спецификаторе формата, потому что он\n", "подразумевается по умолчанию для целых чисел. Второй аргумент –\n", "это имя символа Юникода, которое выводится с помощью метода\n", "`str.title()`, в результате которого первый символ каждого слова\n", "преобразуется к верхнему регистру, а остальные символы – к нижнему. " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Решение квадратного уравнения\n", "
\n", "\n", "Квадратные уравнения – это уравнения вида $ax^2 + bx + c = 0$, где $a \\ne 0$,\n", "описывающие параболу. Корни таких уравнений находятся по формуле\n", "$$\n", "x = \\frac{-b \\pm \\sqrt{b^2-4ac}}{2a}.\n", "$$" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Часть формулы $b^2 – 4ac$ называется дискриминантом – если это\n", "положительная величина, уравнение имеет два действительных корня, если\n", "дискриминант равен нулю – уравнение имеет один действительный корень,\n", "и в случае отрицательного значения уравнение имеет два комплексных\n", "корня. Мы напишем программу, которая будет принимать от пользователя\n", "коэффициенты $a$, $b$ и $c$ (коэффициенты $b$ и c могут быть равны\n", "нулю) и затем вычислять и выводить его корень или корни.\n", "\n", "\n", "Для начала посмотрим, как работает программа:" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "С коэффициентами $1.5$, $-3$ и $6$ программа выведет (некоторые цифры\n", "обрезаны):\n", "\n", "Теперь обратимся к [программному коду](src-datatype/quadratic.py),\n", "который начинается тремя инструкциями `import`:" ] }, { "cell_type": "code", "execution_count": 54, "metadata": { "collapsed": false, "jupyter": { "outputs_hidden": false } }, "outputs": [], "source": [ "import cmath\n", "import math\n", "import sys" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Нам необходимы обе математические библиотеки для работы с числами типа\n", "`float` и `complex`, так как функции, вычисляющие квадратный \n", "корень из вещественных и комплексных чисел, отличаются. Модуль\n", "`sys` нам необходим, так как в нем определена константа\n", "`sys.float_info.epsilon`, которая потребуется нам для сравнения\n", "вещественных чисел со значением `0`.\n", "\n", "Нам также необходима функция, которая будет получать от пользова-\n", "теля число с плавающей точкой:" ] }, { "cell_type": "code", "execution_count": 55, "metadata": { "collapsed": false, "jupyter": { "outputs_hidden": false } }, "outputs": [], "source": [ "def get_float(msg, allow_zero):\n", " x = None\n", " while x is None:\n", " try:\n", " x = float(input(msg))\n", " if not allow_zero and abs(x) < sys.float_info.epsilon:\n", " print(\"zero is not allowed\")\n", " x = None\n", "\n", " except ValueError as err:\n", " print(err)\n", " return x" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Эта функция выполняет цикл, пока пользователь не введет допустимое\n", "число с плавающей точкой (например, `0.5`, `-9`, `21`, `4.92`), и допускает\n", "ввод значения `0`, только если аргумент `allow_zero` имеет значение `True`.\n", "Вслед за определением функции `get_float()` выполняется оставшаяся\n", "часть программного кода. Мы разделим его на три части и начнем со\n", "взаимодействия с пользователем:" ] }, { "cell_type": "code", "execution_count": 56, "metadata": { "collapsed": false, "jupyter": { "outputs_hidden": false } }, "outputs": [], "source": [ "print(\"ax\\N{SUPERSCRIPT TWO} + bx + c = 0\")\n", "a = get_float(\"enter a: \", False)\n", "b = get_float(\"enter b: \", False)\n", "c = get_float(\"enter c: \", False)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Благодаря функции `get_float()` получить значения коэффициентов `a`,\n", "`b` и `c` оказалось очень просто. Второй аргумент функции сообщает, когда\n", "значение `0` является допустимым." ] }, { "cell_type": "code", "execution_count": 57, "metadata": { "collapsed": false, "jupyter": { "outputs_hidden": false } }, "outputs": [], "source": [ "x1 = None\n", "x2 = None\n", "discriminant = (b ** 2) - (4 * a * c)\n", "if discriminant == 0:\n", " x1 = -(b / (2 * a))\n", "else:\n", " if discriminant > 0:\n", " root = math.sqrt(discriminant)\n", " else: # discriminant < 0\n", " root = cmath.sqrt(discriminant)\n", " x1 = (-b + root) / (2 * a)\n", " x2 = (-b - root) / (2 * a)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Программный код выглядит несколько иначе, чем формула, потому\n", "что мы начали вычисления с определения значения дискриминанта.\n", "Если дискриминант равен `0`, мы знаем, что уравнение имеет\n", "единственное действительное решение и можно сразу же вычислить его. В\n", "противном случае мы вычисляем действительный или комплексный\n", "квадратный корень из дискриминанта и находим два корня уравнения." ] }, { "cell_type": "code", "execution_count": 58, "metadata": { "collapsed": false, "jupyter": { "outputs_hidden": false } }, "outputs": [], "source": [ "equation = (\"{0}x\\N{SUPERSCRIPT TWO} + {1}x + {2} = 0\"\n", " \" \\N{RIGHTWARDS ARROW} x = {3}\").format(a, b, c, x1)\n", "if x2 is not None:\n", " equation += \" or x = {0}\".format(x2)\n", "print(equation)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Мы не использовали сколько-нибудь сложного форматирования, поскольку\n", "форматирование, используемое по умолчанию для чисел с плавающей точкой\n", "в языке Python, прекрасно подходит для этого примера, но мы\n", "использовали некоторые имена Юникода для вывода пары специальных\n", "символов." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Представление таблицы `csv` в HTML\n", "
\n", "\n", "Часто бывает необходимо представить данные в формате HTML. В этом\n", "подразделе мы разработаем программу, которая читает данные из\n", "файла в простом формате CSV (Comma Separated Value – значения,\n", "разделенные запятыми) и выводит таблицу HTML, содержащую эти\n", "данные. В составе Python присутствует мощный и сложный модуль\n", "для работы с форматом CSV и похожими на него – модуль csv, но здесь\n", "мы будем выполнять всю обработку вручную.\n", "\n", "В формате CSV каждая запись располагается на одной строке, а поля\n", "внутри записи отделяются друг от друга запятыми. Каждое поле может\n", "быть либо строкой, либо числом. Строки должны окружаться апострофами\n", "или кавычками, а числа не должны окружаться кавычками, если они не\n", "содержат запятые. Внутри строк допускается присутствие запятых, и они\n", "не должны интерпретироваться как разделители полей. Мы будем исходить\n", "из предположения, что первая запись в файле содержит имена полей. На\n", "выходе будет воспроизводиться таблица в формате HTML с выравниванием\n", "текста по левому краю (по умолчанию для HTML) и с выравниванием чисел\n", "по правому краю, по одной строке на запись и по одной ячейке на поле.\n", "\n", "Ниже приводится маленький фрагмент файла с данными:" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ " \"COUNTRY\",2000,2001,2002,2003,2004\n", " \"ANTIGUA AND BARBUDA\",0,0,0,0,0\n", " \"ARGENTINA\",37,35,33,36,39\n", " \"BAHAMAS, THE\",1,1,1,1,1\n", " \"BAHRAIN\",5,6,6,6,6\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Предположим, что данные находятся в файле [sample.csv](src-datatype/sample.csv.txt) и выполнена комадна" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ " Terminal> python csv2html.py < sample.csv > sample.html\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "тогда файл [sample.html](src-datatype/sample.html) должен содержать\n", "примерно следующее:" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
\"Country\"20002001200220032004
\"Antigua and Barbuda\"00000
\"Argentina\"3735333639
\"Bahamas, The\"11111
\"Bahrain\"56666
\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "На рисунке показано, как выглядит полученная таблица в веб-броузере.\n", "\n", "\n", "\n", "
\n", "\n", "![Таблица, произведенная программой csv2html.py, в броузере](fig-datatype/example_1.png)\n", "\n", "\n", "Теперь, когда мы увидели, как используется программа и что она делает,\n", "можно приступать к изучению программного кода.\n", "\n", "Последняя инструкция в программе – это простой вызов функции:" ] }, { "cell_type": "code", "execution_count": 59, "metadata": { "collapsed": false, "jupyter": { "outputs_hidden": false } }, "outputs": [], "source": [ "main()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Хотя в языке Python не требуется явно указывать точку входа в\n", "программу, как в некоторых других языках программирования, тем не\n", "менее является распространенной практикой создание в программе на\n", "языке Python функции с именем `main()`, которая вызывается для\n", "выполнения обработки. Поскольку функция не может вызываться до того,\n", "как она будет определена, мы должны вставлять вызов `main()` только\n", "после того, как данная функция будет определена. Порядок следования\n", "функций в файле (то есть порядок, в котором они создаются) не \n", "имеет значения.\n", "\n", "В программе [csv2html.py](src-datatype/csv2html.py) первой\n", "вызываемой функцией является функция `main()`, которая в свою очередь\n", "вызывает функции `print_start()` и `print_line()`. Функция\n", "`print_line()` вызывает функции `extract_fields()` и `escape_html()`.\n", "\n", "Когда интерпретатор Python читает файл, он начинает делать это с\n", "самого начала. Поэтому сначала будет выполнен импорт (если он есть),\n", "затем будет создана функция `main()`, а затем будут созданы остальные\n", "функции – в том порядке, в каком они следуют в файле. Когда\n", "интерпретатор, наконец, достигнет вызова `main()` в конце файла, все\n", "функции, которые вызываются функцией `main()` (и все функции, которые\n", "вызываются этими функциями), будут определены. Выполнение обработки,\n", "как и следовало ожидать, начинается в точке вызова функции `main()`.\n", "\n", "Рассмотрим все функции по порядку, начиная с функции `main()`." ] }, { "cell_type": "code", "execution_count": 60, "metadata": { "collapsed": false, "jupyter": { "outputs_hidden": false } }, "outputs": [], "source": [ "def main():\n", " maxwidth = 100\n", " print_start()\n", " count = 0\n", " while True:\n", " try:\n", " line = input()\n", " if count == 0:\n", " color = \"lightgreen\"\n", " elif count % 2:\n", " color = \"white\"\n", " else:\n", " color = \"lightyellow\"\n", " print_line(line, color, maxwidth)\n", " count += 1\n", " except EOFError:\n", " break\n", " print_end()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Переменная `maxwidth` используется для хранения числа символов в\n", "ячейке. Если поле больше, чем это число, часть строки отсекается и на\n", "место отброшенного текста добавляется многоточие. Программный код\n", "функций `print_start()`, `print_line()` и `print_end()` будет приведен\n", "чуть ниже. Цикл while выполняет обход всех входных строк – это могут\n", "быть строки, вводимые пользователем с клавиатуры, но мы предполагаем,\n", "что данные будут перенаправлены из файла. Далее выбирается цвет фона и\n", "вызывается функция `print_line()`, которая выводит строку в виде строки\n", "таблицы в формате HTML." ] }, { "cell_type": "code", "execution_count": 61, "metadata": { "collapsed": false, "jupyter": { "outputs_hidden": false } }, "outputs": [], "source": [ "def print_start():\n", " print(\"\")\n", "\n", "def print_end():\n", " print(\"
\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Мы могли бы не создавать эти две функции и просто вставить\n", "соответствующие вызовы `print()` в функцию `main()`. Но мы предпочитаем\n", "выделять логику, так как это делает реализацию более гибкой, хотя\n", "в этом маленьком примере гибкость не имеет большого значения." ] }, { "cell_type": "code", "execution_count": 62, "metadata": { "collapsed": false, "jupyter": { "outputs_hidden": false } }, "outputs": [], "source": [ "def print_line(line, color, maxwidth):\n", " print(\"\".format(color))\n", " fields = extract_fields(line)\n", " for field in fields:\n", " if not field:\n", " print(\"\")\n", " else:\n", " number = field.replace(\",\", \"\")\n", " try:\n", " x = float(number)\n", " print(\"{0:d}\".format(round(x)))\n", " except ValueError:\n", " field = field.title()\n", " field = field.replace(\" And \", \" and \")\n", " field = escape_html(field)\n", " if len(field) <= maxwidth:\n", " print(\"{0}\".format(field))\n", " else:\n", " print(\"{0:.{1}} ...\".format(field, maxwidth))\n", " print(\"\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Мы не можем использовать метод `str.split(\",\")` для разбиения каждой\n", "строки на поля, потому что запятые могут находиться внутри строк в\n", "кавычках. Поэтому мы возложили эту обязанность на функцию\n", "`extract_fields()`. Получив список строк полей (в виде строк без\n", "окружающих их кавычек), мы выполняем обход списка и создаем для \n", "каждого поля ячейку таблицы.\n", "\n", "Если поле пустое, мы выводим пустую ячейку. Если поле было заключено в\n", "кавычки, это может быть строка или число в кавычках, содержащее\n", "символы запятой, например `\"1,566\"`. Учитывая такую возможность, мы\n", "создаем копию поля без запятых и пытаемся преобразовать ее в число\n", "типа `float`. Если преобразование удалось, мы определяем выравнивание\n", "в ячейке по правому краю, а значение поля округляется до ближайшего\n", "целого, которое и выводится. Если преобразование не удалось,\n", "следовательно, поле содержит строку. В этом случае мы с помощью метода\n", "`str.title()` изменяем регистр символов и замещаем слово «And» на слово\n", "«and», устраняя побочный эффект действия метода \n", "`str.title()`. Затем выполняется экранирование специальных символов\n", "HTML и выводится либо поле целиком, либо первые `maxwidth` символов\n", "с добавлением многоточия. Простейшей альтернативой использованию\n", "вложенного поля замены в строке формата является получение \n", "среза строки, например:" ] }, { "cell_type": "code", "execution_count": 63, "metadata": { "collapsed": false, "jupyter": { "outputs_hidden": false } }, "outputs": [], "source": [ "print(\"{0} ...\".format(field[:maxwidth]))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Еще одно преимущество такого подхода состоит в том, что он требует\n", "меньшего объема ввода с клавиатуры." ] }, { "cell_type": "code", "execution_count": 64, "metadata": { "collapsed": false, "jupyter": { "outputs_hidden": false } }, "outputs": [], "source": [ "def extract_fields(line):\n", " fields = []\n", " field = \"\"\n", " quote = None\n", " for c in line:\n", " if c in \"\\\"'\":\n", " if quote is None: # начало строки в кавычках\n", " quote = c\n", " elif quote == c: # конец строки в кавычках\n", " quote = None\n", " else:\n", " field += c\n", " # другая кавычка внутри строки в кавычках\n", " continue\n", " if quote is None and c == \",\": # end of a field\n", " fields.append(field)\n", " field = \"\"\n", " else:\n", " field += c\n", " # добавить символ в поле\n", " if field:\n", " fields.append(field) # добавить последнее поле в список\n", " return fields" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Эта функция читает символы из строки один за другим и накапливает\n", "список полей, где каждое поле – это строка без окружающих ее\n", "кавычек. Функция способна обрабатывать поля, не заключенные в кавычки,\n", "и поля, заключенные в кавычки или в апострофы, корректно обрабатывая\n", "запятые и кавычки (апострофы в строках, заключенных в кавычки, и\n", "кавычки в строках, заключенных в апострофы)." ] }, { "cell_type": "code", "execution_count": 13, "metadata": { "collapsed": false, "jupyter": { "outputs_hidden": false } }, "outputs": [], "source": [ "def escape_html(text):\n", " text = text.replace(\"&\", \"&\")\n", " text = text.replace(\"<\", \"<\")\n", " text = text.replace(\">\", \">\")\n", " return text" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Эта функция просто замещает каждый специальный символ HTML\n", "соответствующей ему сущностью языка HTML. В первую очередь, конечно,\n", "мы должны заменить символ амперсанда и угловые скобки, хотя порядок не\n", "имеет никакого значения. " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "\n", "\n", "\n", "# Упражнения\n", "
" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "\n", "## Изменение вывода символов Юникода\n", "
\n", "\n", "Измените программу `print_unicode.py` так, чтобы пользователь мог\n", "вводить в командной строке несколько разных слов и получать\n", "только те строки из таблицы символов Юникода, в которых содержатся все\n", "слова, указанные пользователем. Это означает, что мы сможем вводить\n", "такие команды:" ] }, { "cell_type": "code", "execution_count": 15, "metadata": { "collapsed": false, "jupyter": { "outputs_hidden": false } }, "outputs": [ { "ename": "SyntaxError", "evalue": "invalid syntax (, line 1)", "output_type": "error", "traceback": [ "\u001b[0;36m File \u001b[0;32m\"\"\u001b[0;36m, line \u001b[0;32m1\u001b[0m\n\u001b[0;31m print_unicode_ans.py greek symbol\u001b[0m\n\u001b[0m ^\u001b[0m\n\u001b[0;31mSyntaxError\u001b[0m\u001b[0;31m:\u001b[0m invalid syntax\n" ] } ], "source": [ "print_unicode_ans.py greek symbol" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "\n", "**Подсказка.**\n", "Один из способов достижения поставленной цели состоит в том,\n", "чтобы заменить переменную `word` (которая может хранить `0`, `None` \n", "или строку) списком `words`. Не забудьте изменить информацию о порядке\n", "использования. В результате изменений не более десяти строк\n", "программного кода добавится и не более десяти строк изменится.\n", "\n", "\n", "Имя файла: `print_unicode_ans.py`.\n", "\n", "" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "\n", "## Изменение `quadratic.py`\n", "
\n", "\n", "Измените программу `quadratic.py` так, чтобы она не выводила\n", "коэффициенты со значением `0.0`, а отрицательные коэффициенты\n", "выводились бы как `-n`, а не `+ - n`.\n", "Имя файла: `quadratic_ans.py`.\n", "\n", "" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "\n", "## Использование функции `escape()`\n", "
\n", "\n", "Удалите функцию `escape_html()` из программы `cvs2html.py` и\n", "используйте вместо нее функцию `xml.sax.saxutils.escape()` из модуля \n", "`xml.sax.saxutils`.\n", "\n", "" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Подсказка.**\n", "Для этого потребуется добавить одну новую строку\n", "(с инструкцией `import`), удалить пять строк (с ненужной функцией)\n", "и изменить одну строку (задействовать функцию\n", "`xml.sax.saxutils.escape()` вместо `escape_html()`).\n", "\n", "\n", "Имя файла: `cvs2html_ans1.py`.\n", "\n", "" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "\n", "## Добавление обработки параметров командной строки в `csv2html.py`\n", "
\n", "\n", "Измените программу `cvs2html.py` еще раз и добавьте в нее новую\n", "функцию с именем `process_options()`. Эта функция должна вызываться из\n", "функции main() и возвращать кортеж с двумя значениями: \n", "`maxwidth` (типа `int`) и `format` (типа `str`). При вызове функция\n", "`process_options()` должна устанавливать `maxwidth` в значение по\n", "умолчанию `100`, а строку `format` – в значение по умолчанию `\".0f\"`,\n", "которое будет использоваться как спецификатор формата при выводе чисел.\n", "Если пользователь вводит в командной строке `-h` или `--help`,\n", "должно выводиться сообщение о порядке использования и возвращаться\n", "кортеж `(None, None)`. (В этом случае функция `main()` ничего\n", "делать не должна.) В противном случае функция должна прочитать\n", "аргументы командной строки и выполнить соответствующие\n", "присваивания. Например, устанавливать значение переменной `maxwidth`,\n", "если задан аргумент `maxwidth=n`, и точно так же устанавливать \n", "значение переменной `format`, если задан аргумент `format=s`. Ниже\n", "приводится сеанс работы с программой, когда пользователь затребовал\n", "инструкцию о порядке работы:" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ " Terminal> csv2html2_ans.py -h\n", " usage:\n", " csv2html.py [maxwidth=int] [format=str] < infile.csv > outfile.html\n", " maxwidth - необязательное целое число. Если задано, определяет\n", " максимальное число символов для строковых полей. В противном случае\n", " используется значение по умолчанию 100.\n", " \n", " format - формат вывода чисел. Если не задан, по умолчанию используется\n", " формат \".0f\".\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "А ниже приводится пример командной строки, в которой установ-\n", "лены оба аргумента:" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ " Terminal> csv2html2_ans.py maxwidth=20 format=0.2f < mydata.csv > mydata.html\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "\n", "**Подсказка.**\n", "Не забудьте изменить функцию `print_line()` так, чтобы она\n", "использовала переменную `format` при выводе чисел – для этого вам\n", "придется передавать функции дополнительный аргумент, добавить одну \n", "строку и изменить еще одну строку. И это немного затронет функцию\n", "`main()`. Функция `process_options()` должна содержать порядка\n", "двадцати пяти строк (включая девять строк с текстом сообщения о\n", "порядке использования).\n", "\n", "\n", "Имя файла: `cvs2html_ans2.py`.\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "" ] } ], "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.2" } }, "nbformat": 4, "nbformat_minor": 4 }