ээдд. Прохоренок_Н_А__Дронов_В_А_Python_3_и_PyQt_5_Разработка_приложен. Николай Прохоренок Владимир Дронов
Скачать 7.92 Mb.
|
-2.7755575615628914e-17 Ожидаемым был бы результат 0.0 , но, как видно из примера, мы получили совсем другое значение. Если необходимо производить операции с фиксированной точностью, то следует использовать модуль decimal : >>> from decimal import Decimal >>> Decimal("0.3") - Decimal("0.1") - Decimal("0.1") - Decimal("0.1") Decimal('0.0') Кроме того, можно использовать дроби, поддержка которых реализована в модуле fractions . При создании дроби можно указать как два числа: числитель и знаменатель, так и одно число или строку, содержащую число, которое будет преобразовано в дробь. Для примера создадим несколько дробей. Вот так формируется дробь 4 / 5 : >>> from fractions import Fraction >>> Fraction(4, 5) Fraction(4, 5) А вот так — дробь 1 / 2 , причем можно сделать это тремя способами: >>> Fraction(1, 2) Fraction(1, 2) >>> Fraction("0.5") Fraction(1, 2) >>> Fraction(0.5) Fraction(1, 2) Над дробями можно производить арифметические операции, как и над обычными числами: >>> Fraction(9, 5) - Fraction(2, 3) Fraction(17, 15) >>> Fraction("0.3") - Fraction("0.1") - Fraction("0.1") - Fraction("0.1") Fraction(0, 1) >>> float(Fraction(0, 1)) 0.0 Комплексные числа записываются в формате: <Вещественная часть>+<Мнимая часть>J Здесь буква J может стоять в любом регистре. Примеры комплексных чисел: >>> 2+5J, 8j ((2+5j), 8j) Подробное рассмотрение модулей decimal и fractions , а также комплексных чисел выхо- дит за рамки нашей книги. За подробной информацией обращайтесь к документации по языку Python. Глава 5. Числа 75 В Python 3.6 появилась возможность для улучшения читаемости кода вставлять в число, записанное в десятичной, двоичной, восьмеричной и шестнадцатеричной системах счисле- ния, символы подчеркивания: >>> 1_000_000 1000000 >>> 0b1111_1111 255 >>> 0o2_777 1535 >>> 0xab_cd 43981 5.1. Встроенные функции и методы для работы с числами Для работы с числами предназначены следующие встроенные функции: int([<Объект>[, <Система счисления>]]) — преобразует объект в целое число. Во вто- ром параметре можно указать систему счисления преобразуемого числа (значение по умолчанию 10 ): >>> int(7.5), int("71", 10), int("0o71", 8), int("0xA", 16) (7, 71, 57, 10) >>> int(), int("0b11111111", 2) (0, 255) float([<Число или строка>]) — преобразует целое число или строку в вещественное число: >>> float(7), float("7.1"), float("12.") (7.0, 7.1, 12.0) >>> float("inf"), float("-Infinity"), float("nan") (inf, -inf, nan) >>> float() 0.0 bin(<Число>) — преобразует десятичное число в двоичное. Возвращает строковое пред- ставление числа: >>> bin(255), bin(1), bin(-45) ('0b11111111', '0b1', '-0b101101') oct(<Число>) — преобразует десятичное число в восьмеричное. Возвращает строковое представление числа: >>> oct(7), oct(8), oct(64) ('0o7', '0o10', '0o100') hex(<Число>) — преобразует десятичное число в шестнадцатеричное. Возвращает стро- ковое представление числа: >>> hex(10), hex(16), hex(255) ('0xa', '0x10', '0xff') 76 Часть I. Основы языка Python round(<Число>[, <Количество знаков после точки>]) — для чисел с дробной частью, меньшей 0.5 , возвращает число, округленное до ближайшего меньшего целого, а для чисел с дробной частью, большей 0.5 , возвращает число, округленное до ближайшего большего целого. Если дробная часть равна 0.5 , то округление производится до бли- жайшего четного числа: >>> round(0.49), round(0.50), round(0.51) (0, 0, 1) >>> round(1.49), round(1.50), round(1.51) (1, 2, 2) >>> round(2.49), round(2.50), round(2.51) (2, 2, 3) >>> round(3.49), round(3.50), round(3.51) (3, 4, 4) Во втором параметре можно указать желаемое количество знаков после запятой. Если оно не указано, используется значение 0 (т. е. число будет округлено до целого): >>> round(1.524, 2), round(1.525, 2), round(1.5555, 3) (1.52, 1.52, 1.556) abs(<Число>) — возвращает абсолютное значение: >>> abs(-10), abs(10), abs(-12.5) (10, 10, 12.5) pow(<Число>, <Степень>[, <Делитель>]) — возводит <Число> в <Степень> : >>> pow(10, 2), 10 ** 2, pow(3, 3), 3 ** 3 (100, 100, 27, 27) Если указан третий параметр, возвращается остаток от деления полученного результата на значение этого параметра: >>> pow(10, 2, 2), (10 ** 2) % 2, pow(3, 3, 2), (3 ** 3) % 2 (0, 0, 1, 1) max(<Список чисел через запятую>) — максимальное значение из списка: >>> max(1, 2, 3), max(3, 2, 3, 1), max(1, 1.0), max(1.0, 1) (3, 3, 1, 1.0) min(<Список чисел через запятую>) — минимальное значение из списка: >>> min(1, 2, 3), min(3, 2, 3, 1), min(1, 1.0), min(1.0, 1) (1, 1, 1, 1.0) sum(<Последовательность>[, <Начальное значение>]) — возвращает сумму значений элементов последовательности (списка, кортежа и пр.) плюс <Начальное значение> . Если второй параметр не указан, начальное значение принимается равным 0 . Если последова- тельность пустая, возвращается значение второго параметра: >>> sum((10, 20, 30, 40)), sum([10, 20, 30, 40]) (100, 100) >>> sum([10, 20, 30, 40], 2), sum([], 2) (102, 2) Глава 5. Числа 77 divmod(x, y) — возвращает кортеж из двух значений (x // y, x % y) : >>> divmod(13, 2) # 13 == 6 * 2 + 1 (6, 1) >>> 13 // 2, 13 % 2 (6, 1) >>> divmod(13.5, 2.0) # 13.5 == 6.0 * 2.0 + 1.5 (6.0, 1.5) >>> 13.5 // 2.0, 13.5 % 2.0 (6.0, 1.5) Следует понимать, что все типы данных, поддерживаемые Python, представляют собой классы. Класс float , представляющий вещественные числа, поддерживает следующие по- лезные методы: is_integer() — возвращает True , если заданное вещественное число не содержит дроб- ной части, т. е. фактически представляет собой целое число: >>> (2.0).is_integer() True >>> (2.3).is_integer() False as_integer_ratio() — возвращает кортеж из двух целых чисел, представляющих собой числитель и знаменатель дроби, которая соответствует заданному числу: >>> (0.5).as_integer_ratio() (1, 2) >>> (2.3).as_integer_ratio() (2589569785738035, 1125899906842624) 5.2. Модуль math: математические функции Модуль math предоставляет дополнительные функции для работы с числами, а также стан- дартные константы. Прежде чем использовать модуль, необходимо подключить его с по- мощью инструкции: import math П РИМЕЧАНИЕ Для работы с комплексными числами необходимо использовать модуль cmath. Модуль math предоставляет следующие стандартные константы: pi — число π: >>> import math >>> math.pi 3.141592653589793 e — константа e: >>> math.e 2.718281828459045 Приведем перечень основных функций для работы с числами: sin() , cos() , tan() — стандартные тригонометрические функции (синус, косинус, тан- генс). Значение указывается в радианах; 78 Часть I. Основы языка Python asin() , acos() , atan() — обратные тригонометрические функции (арксинус, арккосинус, арктангенс). Значение возвращается в радианах; degrees() — преобразует радианы в градусы: >>> math.degrees(math.pi) 180.0 radians() — преобразует градусы в радианы: >>> math.radians(180.0) 3.141592653589793 exp() — экспонента; log(<Число>[, <База>]) — логарифм по заданной базе. Если база не указана, вычисляет- ся натуральный логарифм (по базе e); log10() — десятичный логарифм; log2() — логарифм по базе 2; sqrt() — квадратный корень: >>> math.sqrt(100), math.sqrt(25) (10.0, 5.0) ceil() — значение, округленное до ближайшего большего целого: >>> math.ceil(5.49), math.ceil(5.50), math.ceil(5.51) (6, 6, 6) floor() — значение, округленное до ближайшего меньшего целого: >>> math.floor(5.49), math.floor(5.50), math.floor(5.51) (5, 5, 5) pow(<Число>, <Степень>) — возводит число в степень: >>> math.pow(10, 2), 10 ** 2, math.pow(3, 3), 3 ** 3 (100.0, 100, 27.0, 27) fabs() — абсолютное значение: >>> math.fabs(10), math.fabs(-10), math.fabs(-12.5) (10.0, 10.0, 12.5) fmod() — остаток от деления: >>> math.fmod(10, 5), 10 % 5, math.fmod(10, 3), 10 % 3 (0.0, 0, 1.0, 1) factorial() — факториал числа: >>> math.factorial(5), math.factorial(6) (120, 720) fsum(<Список чисел>) — возвращает точную сумму чисел из заданного списка: >>> sum([.1, .1, .1, .1, .1, .1, .1, .1, .1, .1]) 0.9999999999999999 >>> fsum([.1, .1, .1, .1, .1, .1, .1, .1, .1, .1]) 1.0 Глава 5. Числа 79 П РИМЕЧАНИЕ В этом разделе мы рассмотрели только основные функции. Чтобы получить полный список функций, обращайтесь к документации по модулю math. 5.3. Модуль random: генерирование случайных чисел Модуль random позволяет генерировать случайные числа. Прежде чем использовать модуль, необходимо подключить его с помощью инструкции: import random Приведем перечень его основных функций: random() — возвращает псевдослучайное число от 0.0 до 1.0 : >>> import random >>> random.random() 0.9753144027290991 >>> random.random() 0.5468390487484339 >>> random.random() 0.13015058054767736 seed([<Параметр>][, version=2]) — настраивает генератор случайных чисел на новую последовательность. Если первый параметр не указан, в качестве базы для случайных чисел будет использовано системное время. При одинаковых значениях первого пара- метра будет генерироваться одинаковая последовательность чисел: >>> random.seed(10) >>> random.random() 0.5714025946899135 >>> random.seed(10) >>> random.random() 0.5714025946899135 uniform(<Начало>, <Конец>) — возвращает псевдослучайное вещественное число в диа- пазоне от <Начало> до <Конец> : >>> random.uniform(0, 10) 9.965569925394552 >>> random.uniform(0, 10) 0.4455638245043303 randint(<Начало>, <Конец>) — возвращает псевдослучайное целое число в диапазоне от <Начало> до <Конец> : >>> random.randint(0, 10) 4 >>> random.randint(0, 10) 10 randrange([<Начало>, ]<Конец>[, <Шаг>]) — возвращает случайный элемент из созда- ваемого «за кадром» диапазона. Параметры аналогичны параметрам функции range() : 80 Часть I. Основы языка Python >>> random.randrange(10) 5 >>> random.randrange(0, 10) 2 >>> random.randrange(0, 10, 2) 6 choice(<Последовательность>) — возвращает случайный элемент из заданной последо- вательности (строки, списка, кортежа): >>> random.choice("string") # Строка 'i' >>> random.choice(["s", "t", "r"]) # Список 'r' >>> random.choice(("s", "t", "r")) # Кортеж 't' shuffle(<Список>[, <Число от 0.0 до 1.0>]) — перемешивает элементы списка слу- чайным образом. Если второй параметр не указан, то используется значение, возвра- щаемое функцией random() . Никакого результата при этом не возвращается: >>> arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] >>> random.shuffle(arr) >>> arr [8, 6, 9, 5, 3, 7, 2, 4, 10, 1] sample(<Последовательность>, <Количество элементов>) — возвращает список из ука- занного количества элементов, которые будут выбраны случайным образом из заданной последовательности. В качестве таковой можно указать любые объекты, поддерживаю- щие итерации: >>> random.sample("string", 2) ['i', 'r'] >>> arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] >>> random.sample(arr, 2) [7, 10] >>> arr # Сам список не изменяется [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] >>> random.sample((1, 2, 3, 4, 5, 6, 7), 3) [6, 3, 5] >>> random.sample(range(300), 5) [126, 194, 272, 46, 71] Для примера напишем функцию-генератор паролей произвольной длины (листинг 5.1). Для этого добавим в список arr все разрешенные символы, а далее в цикле будем получать случайный элемент с помощью функции choice() . По умолчанию будет выдаваться пароль из 8 символов. Листинг 5.1. Генератор паролей # -*- coding: utf-8 -*- import random # Подключаем модуль random def passw_generator(count_char=8): Глава 5. Числа 81 arr = ['a','b','c','d','e','f','g','h','i','j','k','l','m', 'n','o','p','q','r','s','t','u','v','w','x','y','z', 'A','B','C','D','E','F','G','H','I','J','K','L', 'M','N','O','P','Q','R','S','T','U','V', 'W', 'X','Y','Z','1','2','3','4','5','6','7','8','9','0'] passw = [] for i in range(count_char): passw.append(random.choice(arr)) return "".join(passw) Испытаем эту функцию в действии: print(passw_generator(10)) # Выведет что-то вроде ngODHE8J8x print(passw_generator()) # Выведет что-то вроде ZxcpkF5O ГЛ А В А 6 Строки и двоичные данные Строки представляют собой последовательности символов. Длина строки ограничена лишь объемом оперативной памяти компьютера. Как и все последовательности, строки поддер- живают обращение к элементу по индексу, получение среза, конкатенацию (оператор + ), повторение (оператор * ), проверку на вхождение (операторы in и not in ). Кроме того, строки относятся к неизменяемым типам данных. Поэтому практически все строковые методы в качестве значения возвращают новую строку. (При использовании не- больших строк это не приводит к каким-либо проблемам, но при работе с большими стро- ками можно столкнуться с проблемой нехватки памяти.) Иными словами, можно получить символ по индексу, но изменить его будет нельзя: >>> s = "Python" >>> s[0] # Можно получить символ по индексу 'P' >>> s[0] = "J" # Изменить строку нельзя Traceback (most recent call last): File " ", line 1, in TypeError: 'str' object does not support item assignment В некоторых языках программирования строка должна заканчиваться нулевым символом. В языке Python нулевой символ может быть расположен внутри строки: >>> "string\x00string" # Нулевой символ — это НЕ конец строки 'string\x00string' Python поддерживает следующие строковые типы: str — Unicode-строка. Обратите внимание, конкретная кодировка: UTF-8, UTF-16 или UTF-32 — здесь не указана. Рассматривайте такие строки, как строки в некой абстракт- ной кодировке, позволяющие хранить символы Unicode и производить манипуляции с ними. При выводе Unicode-строку необходимо преобразовать в последовательность байтов в какой-либо кодировке: >>> type("строка") >>> "строка".encode(encoding="cp1251") b'\xf1\xf2\xf0\xee\xea\xe0' >>> "строка".encode(encoding="utf-8") b'\xd1\x81\xd1\x82\xd1\x80\xd0\xbe\xd0\xba\xd0\xb0' Глава 6. Строки и двоичные данные 83 bytes — неизменяемая последовательность байтов. Каждый элемент последовательно- сти может хранить целое число от 0 до 255 , которое обозначает код символа. Объект типа bytes поддерживает большинство строковых методов и, если это возможно, выво- дится как последовательность символов. Однако доступ по индексу возвращает целое число, а не символ: >>> s = bytes("стр str", "cp1251") >>> s[0], s[5], s[0:3], s[4:7] (241, 116, b'\xf1\xf2\xf0', b'str') >>> s b'\xf1\xf2\xf0 str' Объект типа bytes может содержать как однобайтовые, так и многобайтовые символы. Обратите внимание на то, что функции и методы строк некорректно работают с много- байтовыми кодировками, — например, функция len() вернет количество байтов, а не символов: >>> len("строка") 6 >>> len(bytes("строка", "cp1251")) 6 >>> len(bytes("строка", "utf-8")) 12 bytearray — изменяемая последовательность байтов. Тип bytearray аналогичен типу bytes , но позволяет изменять элементы по индексу и содержит дополнительные методы, дающие возможность добавлять и удалять элементы: >>> s = bytearray("str", "cp1251") >>> s[0] = 49; s # Можно изменить символ bytearray(b'1tr') >>> s.append(55); s # Можно добавить символ bytearray(b'1tr7') Во всех случаях, когда речь идет о текстовых данных, следует использовать тип str . Имен- но этот тип мы будем называть словом «строка». Типы bytes и bytearray следует задейст- вовать для записи двоичных данных (например, изображений) и промежуточного хранения строк. Более подробно типы bytes и bytearray мы рассмотрим в конце этой главы. 6.1. Создание строки Создать строку можно следующими способами: с помощью функции str([<Объект>[, <Кодировка>[, <Обработка ошибок>]]]) . Если указан только первый параметр, функция возвращает строковое представление любого объекта. Если параметры не указаны вообще, возвращается пустая строка: >>> str(), str([1, 2]), str((3, 4)), str({"x": 1}) ('', '[1, 2]', '(3, 4)', "{'x': 1}") >>> str(b"\xf1\xf2\xf0\xee\xea\xe0") "b'\\xf1\\xf2\\xf0\\xee\\xea\\xe0'" Обратите внимание на преобразование объекта типа bytes . Мы получили строковое представление объекта, а не нормальную строку. Чтобы получить из объектов типа bytes и bytearray именно строку, следует указать кодировку во втором параметре: 84 Часть I. Основы языка Python >>> str(b"\xf1\xf2\xf0\xee\xea\xe0", "cp1251") 'строка' В третьем параметре могут быть указаны значения "strict" (при ошибке возбуждается исключение UnicodeDecodeError — значение по умолчанию), "replace" (неизвестный символ заменяется символом, имеющим код \uFFFD ) или "ignore" (неизвестные символы игнорируются): >>> obj1 = bytes("строка1", "utf-8") >>> obj2 = bytearray("строка2", "utf-8") >>> str(obj1, "utf-8"), str(obj2, "utf-8") ('строка1', 'строка2') >>> str(obj1, "ascii", "strict") Traceback (most recent call last): File " ", line 1, in UnicodeDecodeError: 'ascii' codec can't decode byte 0xd1 in position 0: ordinal not in range(128) >>> str(obj1, "ascii", "ignore") '1' указав строку между апострофами или двойными кавычками: >>> 'строка', "строка", '"x": 5', "'x': 5" ('строка', 'строка', '"x": 5', "'x': 5") >>> print('Строка1\nСтрока2') Строка1 Строка2 >>> print("Строка1\nСтрока2") Строка1 Строка2 В некоторых языках программирования (например, в PHP) строка в апострофах отлича- ется от строки в кавычках тем, что внутри апострофов специальные символы выводятся как есть, а внутри кавычек они интерпретируются. В языке Python никакого отличия между строкой в апострофах и строкой в кавычках нет. Если строка содержит кавычки, то ее лучше заключить в апострофы, и наоборот. Все специальные символы в таких строках интерпретируются — например, последовательность символов \n преобразуется в символ новой строки. Чтобы специальный символ выводился как есть, его необходимо экранировать с помощью слэша: >>> print("Строка1\\nСтрока2") Строка1\nСтрока2 >>> print('Строка1\\nСтрока2') Строка1\nСтрока2 Кавычку внутри строки в кавычках и апостроф внутри строки в апострофах также необ- ходимо экранировать с помощью защитного слэша: >>> "\"x\": 5", '\'x\': 5' ('"x": 5', "'x': 5") Следует также заметить, что заключить объект в одинарные кавычки (или апострофы) на нескольких строках нельзя. Переход на новую строку вызовет синтаксическую ошибку: >>> "string SyntaxError: EOL while scanning string literal Глава 6. Строки и двоичные данные 85 Чтобы расположить объект на нескольких строках, следует перед символом перевода строки указать символ \ , поместить две строки внутри скобок или использовать конка- тенацию внутри скобок: >>> "string1\ string2" # После \ не должно быть никаких символов 'string1string2' >>> ("string1" "string2") # Неявная конкатенация строк 'string1string2' >>> ("string1" + "string2") # Явная конкатенация строк 'string1string2' Кроме того, если в конце строки расположен символ \ , то его необходимо экранировать, иначе будет выведено сообщение об ошибке: >>> print("string\") SyntaxError: EOL while scanning string literal >>> print("string\\") string\ указав строку между утроенными апострофами или утроенными кавычками. Такие объ- екты можно разместить на нескольких строках. Допускается также одновременно ис- пользовать и кавычки, и апострофы без необходимости их экранировать. В остальном такие объекты эквивалентны строкам в апострофах и кавычках. Все специальные симво- лы в таких строках интерпретируются: >>> print('''Строка1 Строка2''') Строка1 Строка2 >>> print("""Строка1 Строка2""") Строка1 Строка2 Если строка не присваивается переменной, то она считается строкой документирования. Такая строка сохраняется в атрибуте __doc__ того объекта, в котором расположена. В каче- стве примера создадим функцию со строкой документирования, а затем выведем содержи- мое строки: >>> def test(): """Это описание функции""" pass >>> print(test.__doc__) Это описание функции Поскольку выражения внутри таких строк не выполняются, то утроенные кавычки (или утроенные апострофы) очень часто используются для комментирования больших фрагмен- тов кода на этапе отладки программы. 86 Часть I. Основы языка Python Если перед строкой разместить модификатор r , то специальные символы внутри строки выводятся как есть. Например, символ \n не будет преобразован в символ перевода строки. Иными словами, он будет считаться последовательностью символов \ и n : >>> print("Строка1\nСтрока2") Строка1 Строка2 >>> print(r"Строка1\nСтрока2") Строка1\nСтрока2 >>> print(r"""Строка1\nСтрока2""") Строка1\nСтрока2 Такие неформатированные строки удобно использовать в шаблонах регулярных выраже- ний, а также при указании пути к файлу или каталогу: >>> print(r"C:\Python36\lib\site-packages") C:\Python36\lib\site-packages Если модификатор не указать, то все слэши при указании пути необходимо экранировать: >>> print("C:\\Python36\\lib\\site-packages") C:\Python36\lib\site-packages Если в конце неформатированной строки расположен слэш, то его необходимо экраниро- вать. Однако следует учитывать, что этот слэш будет добавлен в исходную строку: >>> print(r"C:\Python36\lib\site-packages\") SyntaxError: EOL while scanning string literal >>> print(r"C:\Python36\lib\site-packages\\") C:\Python36\lib\site-packages\\ Чтобы избавиться от лишнего слэша, можно использовать операцию конкатенации строк, обычные строки или удалить слэш явным образом: >>> print(r"C:\Python36\lib\site-packages" + "\\") # Конкатенация C:\Python36\lib\site-packages\ >>> print("C:\\Python36\\lib\\site-packages\\") # Обычная строка C:\Python36\lib\site-packages\ >>> print(r"C:\Python36\lib\site-packages\\"[:-1]) # Удаление слэша C:\Python36\lib\site-packages\ 6.2. Специальные символы Специальные символы — это комбинации знаков, обозначающих служебные или непеча- таемые символы, которые невозможно вставить обычным способом. Приведем перечень спе- циальных символов, допустимых внутри строки, перед которой нет модификатора r : \n — перевод строки; \r — возврат каретки; \t — знак табуляции; \v — вертикальная табуляция; \a — звонок; Глава 6. Строки и двоичные данные 87 \b — забой; \f — перевод формата; \0 — нулевой символ (не является концом строки); \" — кавычка; \' — апостроф; \N — символ с восьмеричным кодом N . Например, \74 соответствует символу < ; \xN — символ с шестнадцатеричным кодом N . Например, \x6a соответствует символу j ; \\ — обратный слэш; \uxxxx — 16-битный символ Unicode. Например, \u043a соответствует русской букве к ; \Uxxxxxxxx — 32-битный символ Unicode. Если после слэша не стоит символ, который вместе со слэшем интерпретируется как спец- символ, то слэш сохраняется в составе строки: >>> print("Этот символ \не специальный") Этот символ \не специальный Тем не менее, лучше экранировать слэш явным образом: >>> print("Этот символ \\не специальный") Этот символ \не специальный 6.3. Операции над строками Как вы уже знаете, строки относятся к последовательностям. Как и все последовательности, строки поддерживают обращение к элементу по индексу, получение среза, конкатенацию, повторение и проверку на вхождение. Рассмотрим эти операции подробно. К любому символу строки можно обратиться как к элементу списка — достаточно указать его индекс в квадратных скобках. Нумерация начинается с нуля: >>> s = "Python" >>> s[0], s[1], s[2], s[3], s[4], s[5] ('P', 'y', 't', 'h', 'o', 'n') Если символ, соответствующий указанному индексу, отсутствует в строке, возбуждается исключение IndexError : >>> s = "Python" >>> s[10] Traceback (most recent call last): File " ", line 1, in IndexError: string index out of range В качестве индекса можно указать отрицательное значение. В этом случае смещение будет отсчитываться от конца строки, а точнее — чтобы получить положительный индекс, значе- ние вычитается из длины строки: >>> s = "Python" >>> s[-1], s[len(s)-1] ('n', 'n') 88 Часть I. Основы языка Python Так как строки относятся к неизменяемым типам данных, то изменить символ по индексу нельзя: >>> s = "Python" >>> s[0] = "J" # Изменить строку нельзя Traceback (most recent call last): File " ", line 1, in TypeError: 'str' object does not support item assignment Чтобы выполнить изменение, можно воспользоваться операцией извлечения среза, которая возвращает указанный фрагмент строки. Формат операции: [<Начало>:<Конец>:<Шаг>] Все параметры здесь не являются обязательными. Если параметр <Начало> не указан, то ис- пользуется значение 0 . Если параметр <Конец> не указан, то возвращается фрагмент до кон- ца строки. Следует также заметить, что символ с индексом, указанным в этом параметре, не входит в возвращаемый фрагмент. Если параметр <Шаг> не указан, то используется значе- ние 1 . В качестве значения параметров можно указать отрицательные значения. Рассмотрим несколько примеров: сначала получим копию строки: >>> s = "Python" >>> s[:] # Возвращается фрагмент от позиции 0 до конца строки 'Python' теперь выведем символы в обратном порядке: >>> s[::-1] # Указываем отрицательное значение в параметре <Шаг> 'nohtyP' заменим первый символ в строке: >>> "J" + s[1:] # Извлекаем фрагмент от символа 1 до конца строки 'Jython' удалим последний символ: >>> s[:-1] # Возвращается фрагмент от 0 до len(s)-1 'Pytho' получим первый символ в строке: >>> s[0:1] # Символ с индексом 1 не входит в диапазон 'P' а теперь получим последний символ: >>> s[-1:] # Получаем фрагмент от len(s)-1 до конца строки 'n' и, наконец, выведем символы с индексами 2, 3 и 4: >>> s[2:5] # Возвращаются символы с индексами 2, 3 и 4 'tho' Узнать количество символов в строке (ее длину) позволяет функция len() : >>> len("Python"), len("\r\n\t"), len(r"\r\n\t") (6, 3, 6) Глава 6. Строки и двоичные данные 89 Теперь, когда мы знаем количество символов, можно перебрать все символы с помощью цикла for : >>> s = "Python" >>> for i in range(len(s)): print(s[i], end=" ") Результат выполнения: P y t h o n Так как строки поддерживают итерации, мы можем просто указать строку в качестве пара- метра цикла: >>> s = "Python" >>> for i in s: print(i, end=" ") Результат выполнения будет таким же: P y t h o n Соединить две строки в одну строку (выполнить их конкатенацию) позволяет оператор + : >>> print("Строка1" + "Строка2") Строка1Строка2 Кроме того, можно выполнить неявную конкатенацию строк. В этом случае две строки ука- зываются рядом без оператора между ними: >>> print("Строка1" "Строка2") Строка1Строка2 Обратите внимание на то, что если между строками указать запятую, то мы получим кор- теж, а не строку: >>> s = "Строка1", "Строка2" >>> type(s) # Получаем кортеж, а не строку Если соединяются, например, переменная и строка, то следует обязательно указывать сим- вол конкатенации строк, иначе будет выведено сообщение об ошибке: >>> s = "Строка1" >>> print(s + "Строка2") # Нормально Строка1Строка2 >>> print(s "Строка2") # Ошибка SyntaxError: invalid syntax При необходимости соединить строку со значением другого типа (например, с числом) сле- дует произвести явное преобразование типов с помощью функции str() : >>> "string" + str(10) 'string10' Кроме рассмотренных операций, строки поддерживают операцию повторения, проверки на вхождение и невхождение. Повторить строку указанное количество раз можно с помощью оператора * , выполнить проверку на вхождение фрагмента в строку позволяет оператор in , а проверить на невхождение — оператор not in : >>> "-" * 20 '--------------------' >>> "yt" in "Python" # Найдено True 90 Часть I. Основы языка Python >>> "yt" in "Perl" # Не найдено False >>> "PHP" not in "Python" # Не найдено True 6.4. Форматирование строк Вместо соединения строк с помощью оператора + лучше использовать форматирование. Эта операция позволяет соединять строки со значениями любых других типов и выполняется быстрее конкатенации. П РИМЕЧАНИЕ В последующих версиях Python оператор форматирования % может быть удален. Вместо этого оператора в новом коде следует использовать метод format(), который рассматри- вается в следующем разделе. Операция форматирования записывается следующим образом: <Строка специального формата> % <Значения> Внутри параметра <Строка специального формата> могут быть указаны спецификаторы, имеющие следующий синтаксис: %[(<Ключ>)][<Флаг>][<Ширина>][.<Точность>]<Тип преобразования> Количество спецификаторов внутри строки должно быть равно количеству элементов в па- раметре <Значения> . Если используется только один спецификатор, то параметр <Значения> может содержать одно значение, в противном случае необходимо указать значения через запятую внутри круглых скобок, создавая тем самым кортеж: >>> "%s" % 10 # Один элемент '10' >>> "%s — %s — %s" % (10, 20, 30) # Несколько элементов '10 — 20 — 30' Параметры внутри спецификатора имеют следующий смысл: <Ключ> — ключ словаря. Если задан ключ, то в параметре <Значения> необходимо ука- зать словарь, а не кортеж: >>> "%(name)s — %(year)s" % {"year": 1978, "name": "Nik"} 'Nik — 1978' <Флаг> — флаг преобразования. Может содержать следующие значения: • # — для восьмеричных значений добавляет в начало комбинацию символов 0o , для шестнадцатеричных значений — комбинацию символов 0x (если используется тип x ) или 0X (если используется тип X ), для вещественных чисел предписывает всегда вы- водить дробную точку, даже если задано значение 0 в параметре <Точность> : >>> print("%#o %#o %#o" % (0o77, 10, 10.5)) 0o77 0o12 0o12 >>> print("%#x %#x %#x" % (0xff, 10, 10.5)) 0xff 0xa 0xa >>> print("%#X %#X %#X" % (0xff, 10, 10.5)) 0XFF 0XA 0XA Глава 6. Строки и двоичные данные 91 >>> print("%#.0F %.0F" % (300, 300)) 300. 300 • 0 — задает наличие ведущих нулей для числового значения: >>> "'%d' — '%05d'" % (3, 3) # 5 — ширина поля "'3' — '00003'" • - — задает выравнивание по левой границе области. По умолчанию используется выравнивание по правой границе. Если флаг указан одновременно с флагом 0 , то действие флага 0 будет отменено: >>> "'%5d' - '%-5d'" % (3, 3) # 5 — ширина поля "' 3' - '3 '" >>> "'%05d' - '%-05d'" % (3, 3) "'00003' - '3 '" • пробел — вставляет пробел перед положительным числом. Перед отрицательным числом будет стоять минус: >>> "'% d' - '% d'" % (-3, 3) "'-3' - ' 3'" • + — задает обязательный вывод знака как для отрицательных, так и для положитель- ных чисел. Если флаг + указан одновременно с флагом пробел , то действие флага про- бел будет отменено: >>> "'%+d' - '%+d'" % (-3, 3) "'-3' - '+3'" <Ширина> — минимальная ширина поля. Если строка не помещается в указанную шири- ну, значение игнорируется, и строка выводится полностью: >>> "'%10d' - '%-10d'" % (3, 3) "' 3' - '3 '" >>> "'%3s''%10s'" % ("string", "string") "'string'' string'" Вместо значения можно указать символ « * ». В этом случае значение следует задать внутри кортежа: >>> "'%*s''%10s'" % (10, "string", "str") "' string'' str'" <Точность> — количество знаков после точки для вещественных чисел. Перед этим параметром обязательно должна стоять точка: >>> import math >>> "%s %f %.2f" % (math.pi, math.pi, math.pi) '3.141592653589793 3.141593 3.14' Вместо значения можно указать символ « * ». В этом случае значение следует задать внутри кортежа: >>> "'%*.*f'" % (8, 5, math.pi) "' 3.14159'" <Тип преобразования> — задает тип преобразования. Параметр является обязательным. 92 Часть I. Основы языка Python В параметре <Тип преобразования> могут быть указаны следующие символы: • s — преобразует любой объект в строку с помощью функции str() : >>> print("%s" % ("Обычная строка")) Обычная строка >>> print("%s %s %s" % (10, 10.52, [1, 2, 3])) 10 10.52 [1, 2, 3] • r — преобразует любой объект в строку с помощью функции repr() : >>> print("%r" % ("Обычная строка")) 'Обычная строка' • a — преобразует объект в строку с помощью функции ascii() : >>> print("%a" % ("строка")) '\u0441\u0442\u0440\u043e\u043a\u0430' • c — выводит одиночный символ или преобразует числовое значение в символ. В ка- честве примера выведем числовое значение и соответствующий этому значению символ: >>> for i in range(33, 127): print("%s => %c" % (i, i)) • d и i — возвращают целую часть числа: >>> print("%d %d %d" % (10, 25.6, -80)) 10 25 -80 >>> print("%i %i %i" % (10, 25.6, -80)) 10 25 -80 • o — восьмеричное значение: >>> print("%o %o %o" % (0o77, 10, 10.5)) 77 12 12 >>> print("%#o %#o %#o" % (0o77, 10, 10.5)) 0o77 0o12 0o12 • x — шестнадцатеричное значение в нижнем регистре: >>> print("%x %x %x" % (0xff, 10, 10.5)) ff a a >>> print("%#x %#x %#x" % (0xff, 10, 10.5)) 0xff 0xa 0xa • X — шестнадцатеричное значение в верхнем регистре: >>> print("%X %X %X" % (0xff, 10, 10.5)) FF A A >>> print("%#X %#X %#X" % (0xff, 10, 10.5)) 0XFF 0XA 0XA • f и F — вещественное число в десятичном представлении: >>> print("%f %f %f" % (300, 18.65781452, -12.5)) 300.000000 18.657815 -12.500000 >>> print("%F %F %F" % (300, 18.65781452, -12.5)) 300.000000 18.657815 -12.500000 >>> print("%#.0F %.0F" % (300, 300)) 300. 300 Глава 6. Строки и двоичные данные 93 • e — вещественное число в экспоненциальной форме (буква e в нижнем регистре): >>> print("%e %e" % (3000, 18657.81452)) 3.000000e+03 1.865781e+04 • E — вещественное число в экспоненциальной форме (буква E в верхнем регистре): >>> print("%E %E" % (3000, 18657.81452)) 3.000000E+03 1.865781E+04 • g — эквивалентно f или e (выбирается более короткая запись числа): >>> print("%g %g %g" % (0.086578, 0.000086578, 1.865E-005)) 0.086578 8.6578e-05 1.865e-05 • G — эквивалентно f или E (выбирается более короткая запись числа): >>> print("%G %G %G" % (0.086578, 0.000086578, 1.865E-005)) 0.086578 8.6578E-05 1.865E-05 Если внутри строки необходимо использовать символ процента, этот символ следует удво- ить, иначе будет выведено сообщение об ошибке: >>> print("% %s" % ("- это символ процента")) # Ошибка Traceback (most recent call last): File " ", line 1, in TypeError: not all arguments converted during string formatting >>> print("%% %s" % ("- это символ процента")) # Нормально % — это символ процента Форматирование строк очень удобно использовать при передаче данных в шаблон веб- страницы. Для этого заполняем словарь данными и указываем его справа от символа % , а сам шаблон — слева. Продемонстрируем это на примере (листинг 6.1). Листинг 6.1. Пример использования форматирования строк # -*- coding: utf-8 -*- html = """ |