Программирование на Python 3. Руководство издательство СимволПлюс
Скачать 3.74 Mb.
|
79 тогда метод x.as_integer_ratio() вернет (11, 4). Преобразование целых чисел в тип float можно выполнить с помощью функции float(). Числа с плавающей точкой также могут быть представлены в виде строк в шестнадцатеричном формате с помощью метода float.hex(). Обратное преобразование может быть выполнено с помощью метода float.fromhex() 1 Например: s = 14.25.hex() # str s == '0x1.c800000000000p+3' f = float.fromhex(s) # float f == 14.25 t = f.hex() # str t == '0x1.c800000000000p+3' Экспонента отмечается с помощью символа p («power» – «степень»), а не e, так как символ e представляет допустимую шестнадцатеричную цифру. В дополнение к встроенным функциональным возможностям работы с числами типа float модуль math предоставляет множество функций, которые приводятся в табл. 2.5. Ниже приводятся несколько фрагмен тов программного кода, демонстрирующих, как можно использовать функциональные возможности модуля: >>> import math >>> math.pi * (5 ** 2) 78.539816339744831 >>> math.hypot(5, 12) 13.0 >>> math.modf(13.732) (0.73199999999999932, 13.0) Функция math.hypot() вычисляет расстояние от начала координат до точки (x, y) и дает тот же результат, что и выражение math.sqrt((x ** 2) + (y ** 2)) Модуль math в значительной степени опирается на математическую библиотеку, с которой был собран интерпретатор Python. Это означа ет, что при некоторых условиях и в граничных случаях функции мо дуля могут иметь различное поведение на различных платформах. Таблица 2.5. Функции и константы модуля math 1 Примечание для программистов, использующих объектноориентирован ный стиль: float.fromhex() – это метод класса. Синтаксис Описание math.acos(x) Возвращает арккосинус x в радианах math.acosh(x) Возвращает гиперболический арккосинус x в радианах math.asin(x) Возвращает арксинус x в радианах math.asinh(x) Возвращает гиперболический арксинус x в радианах math.atan(x) Возвращает арктангенс x в радианах 80 Глава 2. Типы данных Таблица 2.5 (продолжение) Синтаксис Описание 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) Возвращает math.isinf(x) Возвращает True, если значение x типа float является бес конечностью (±inf(± ∞)) math.isnan(x) Возвращает True, если значение x типа float не является числом math.ldexp(m, e) Возвращает m × 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 Кортежи, стр. 32, 130 x 2 y 2 + Тип чисел с плавающей точкой 81 Комплексные числа Тип данных complex относится к категории неизменяемых и хранит па ру значений типа float, одно из которых представляет действитель ную часть комплексного числа, а другое – мнимую. Литералы ком плексных чисел записываются как действительная и мнимая части, объединенные знаком + или – , а за мнимой частью числа следует сим вол j. 1 Вот примеры нескольких комплексных чисел: 3.5+2j, 0.5j, 4+0j, – 1 – 3.7j . Обратите внимание, что если действительная часть числа рав на 0, ее можно вообще опустить. Отдельные части комплексного числа доступны в виде атрибутов real и imag. Например: >>> z = 89.5+2.125j >>> z.real, z.imag (89.5, 2.125) За исключением //, %, divmod() и версии pow() с тремя аргументами все остальные арифметические операторы и функции, перечисленные в табл. 2.2 (стр. 74), могут использоваться для работы с комплексны ми числами, так же как и соответствующие комбинированные опера торы присваивания. Кроме того, значения типа complex имеют метод conjugate() , который изменяет знак мнимой части. Например: math.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) Возвращает math.sum(i) Возвращает сумму значений в итерируемом объекте i в виде числа типа float a math.tan(x) Возвращает тангенс x в радианах math.tanh(x) Возвращает гиперболический тангенс x в радианах math.trunc(x) Возвращает целую часть числа x в виде значения типа int; то же самое, что и int(x) a Функции math.sum в модуле math нет; предполагаю, что эта функция в Py thon 3.0 вытеснена функцией math.fsum. – Прим. перев. 1 В математике, чтобы показать , используется символ i, но в Python, следуя инженерной традиции, используется символ j. Синтаксис Описание x – 1 82 Глава 2. Типы данных >>> z.conjugate() (89.52.125j) >>> 34j.conjugate() (3+4j) Обратите внимание, что в этом примере был вызван метод для литера ла комплексного числа. Вообще, язык Python позволяет вызывать ме тоды любого литерала или обращаться к его атрибутам при условии, что тип данных литерала имеет вызываемый метод или атрибут. Одна ко это не относится к специальным методам, так как им всегда соот ветствуют определенные операторы, которые и должны использовать ся. Например, выражение 4j.real вернет 0.0, выражение 4j.imag вер нет 4.0 и выражение 4j + 3+2j вернет 3+6j. Тип данных complex может вызываться как функция – без аргументов она вернет значение 0j, с аргументом типа complex она вернет копию аргумента, а с аргументом любого другого типа она попытается преоб разовать указанный объект в значение типа complex. При использова нии для преобразования функция complex() принимает либо единст венный строковый аргумент, либо одно или два значения типа float. Если ей передается единственное значение типа float, возвращается комплексное число с мнимой частью, равной 0j. Функции в модуле math не работают с комплексными числами. Это сде лано преднамеренно, чтобы гарантировать, что пользователи модуля math будут получать исключения вместо получения комплексных чи сел в некоторых случаях. Если возникает необходимость использовать комплексные числа, можно воспользоваться модулем cmath, который содержит комплекс ные версии большинства тригонометрических и логарифмических функций, присутствующих в модуле math, плюс ряд функций, специ ально предназначенных для работы с комплексными числами, таких как cmath.phase(), cmath.polar() и cmath.rect(), а также константы cmath.pi и cmath.e, которые хранят те же самые значения типа float, что и родственные им константы в модуле math. Числа типа Decimal Во многих приложениях недостаток точности, свойственный числам типа float, не имеет существенного значения, и эта неточность окупа ется скоростью вычислений. Но в некоторых случаях предпочтение отдается точности, даже в обмен на снижение скорости работы. Мо дуль decimal реализует неизменяемый числовой тип Decimal, который представляет числа с задаваемой точностью. Вычисления с участием таких чисел производятся значительно медленнее, чем в случае ис пользования значений типа float, но насколько это важно, будет зави сеть от приложения. Тип чисел с плавающей точкой 83 Чтобы создать объект типа Decimal, необходимо импортировать модуль decimal . Например: >>> import decimal >>> a = decimal.Decimal(9876) >>> b = decimal.Decimal("54321.012345678987654321") >>> a + b Decimal('64197.012345678987654321') Числа типа Decimal создаются с помощью функции decimal.Decimal(). Эта функция может принимать целочисленный или строковый аргу мент, но не значение типа float, потому что числа типа float не всегда имеют точное представление, а числа типа Decimal всегда представля ются точно. Если в качестве аргумента используется строка, она мо жет содержать изображение числа как в обычной десятичной форме записи, так и в экспоненциальной. Кроме того, возможность явно оп ределить точность представления числа decimal.Decimal означает, что они надежно могут проверяться на равенство. Все арифметические операторы и функции, перечисленные в табл. 2.2 (стр. 74), включая соответствующие им комбинированные операторы присваивания, могут использоваться применительно к значениям ти па decimal.Decimal, но с некоторыми ограничениями. Если слева от опе ратора ** находится объект типа decimal.Decimal, то справа от операто ра должно быть целое число. Точно так же, если первый аргумент функции pow() имеет тип decimal.Decimal, то второй и необязательный третий аргументы должны быть целыми числами. Модули math и cmath не могут использоваться для работы с числами типа decimal.Decimal , однако некоторые функции, присутствующие в модуле math , реализованы как методы типа decimal.Decimal. Например, чтобы вычислить e x , где x имеет тип float, вызывается функция math.exp(x), а когда x имеет тип decimal.Decimal, следует использовать метод x.exp(). Из обсуждения составляющей №3 (стр. 34) мы можем видеть, что x.exp() – это фактически разновидность записи decimal.Decimal.exp(x). Кроме того, тип данных decimal.Decimal предоставляет метод ln(), ко торый вычисляет натуральные (по основанию e) логарифмы (точно так же, как функция math.log() с одним аргументом), log10() и sqrt(), а также множество других методов, адаптированных для обработки значений типа decimal.Decimal. Значения типа decimal.Decimal работают в пределах контекста, где контекст – это коллекция параметров настройки, определяющих пове дение чисел decimal.Decimal. Контекст определяет точность представ ления (по умолчанию 28 десятичных знаков), методику округления и некоторые другие особенности. В некоторых ситуациях различия в точности представления между ти пами float и decimal.Decimal становятся очевидными: 84 Глава 2. Типы данных >>> 23 / 1.05 21.904761904761905 >>> print(23 / 1.05) 21.9047619048 >>> print(decimal.Decimal(23) / decimal.Decimal("1.05")) 21.90476190476190476190476190 >>> decimal.Decimal(23) / decimal.Decimal("1.05") Decimal('21.90476190476190476190476190') Хотя деление чисел decimal.Decimal выполняется с более высокой точ ностью, чем деление чисел float, в данном случае (в 32битной систе ме) различия обнаруживаются только в пятнадцатом знаке после деся тичной точки. Во многих ситуациях такая неточность не имеет боль шого значения, например, в этой книге, где во всех примерах с участи ем чисел с плавающей точкой используются числа типа float. С другой стороны, следует отметить, что последние два приведенных примера впервые демонстрируют, что печать объекта вызывает неко торое закулисное форматирование. Когда для вывода результата выра жения decimal.Decimal(23)/decimal.Decimal("1.05") вызывается функция print() , выводится «голое» число – вывод имеет строковую форму. Ес ли же просто вводится выражение, то на экран выводится decimal.De cimal – в данном случае вывод имеет репрезентативную форму. Все объекты в языке Python имеют две формы вывода. Строковая форма предназначена для вывода информации для человека. Репрезентатив ная форма является представлением объекта, которое можно передать интерпретатору Python (если это необходимо) и воспроизвести пред ставляемый объект. Мы вернемся к этой теме в следующем разделе, когда будем обсуждать строки, и еще раз – в главе 6, когда будем обсу ждать вопросы реализации строковой и репрезентативной формы для наших собственных типов данных. В документе «Library Reference» модуль decimal описывается во всех подробностях, которые выходят далеко за рамки этой книги. Кроме того, там приводится множество примеров и список часто задаваемых вопросов с ответами на них. Строки Строки в языке Python представлены неизменяемым ти пом данных str, который хранит последовательность символов Юникода. Тип данных str может вызываться как функция для создания строковых объектов – без ар гументов возвращается пустая строка; с аргументом, ко торый не является строкой, возвращается строковое представление аргумента; а в случае, когда аргумент яв ляется строкой, возвращается его копия. Функция str() может также использоваться как функция преобразова ния. В этом случае первый аргумент должен быть стро Кодировки символов, стр. 112 Строки 85 кой или объектом, который можно преобразовать в строку, а, кроме того, функции может быть передано до двух необязательных строко вых аргументов, один из которых определяет используемую кодиров ку, а второй определяет порядок обработки ошибок кодирования. Ранее мы уже упоминали, что литералы строк создаются с использо ванием кавычек или апострофов, при этом важно, чтобы с обоих кон цов литерала использовались кавычки одного и того же типа. В допол нение к этому мы можем использовать строки в тройных кавычках, то есть строки, которые начинаются и заканчиваются тремя символа ми кавычки (либо тремя кавычками, либо тремя апострофами). На пример: text = """Строки в тройных кавычках могут включать 'апострофы' и "кавычки" без лишних формальностей. Мы можем даже экранировать символ перевода строки \, благодаря чему данная конкретная строка будет занимать всего две строки.""" Если нам потребуется использовать кавычки в строке, это можно сде лать без лишних формальностей – при условии, что они отличаются от кавычек, ограничивающих строку; в противном случае символы ка вычек или апострофов внутри строки следует экранировать: a = "Здесь 'апострофы' можно не экранировать, а \"кавычки\" придется." b = 'Здесь \'апострофы\' придется экранировать, а "кавычки" не обязательно.' В языке Python символ перевода строки интерпретируется как завер шающий символ инструкции, но не внутри круглых скобок (()), квад ратных скобок ([]), фигурных скобок ({}) и строк в тройных кавычках. Символы перевода строки могут без лишних формальностей использо ваться в строках в тройных кавычках, и мы можем включать символы перевода строки в любые строковые литералы с помощью экраниро ванной последовательности \n. Все экранированные последовательно сти, допустимые в языке Python, перечислены в табл. 2.6. В некото рых ситуациях, например, при записи регулярных выражений, при ходится создавать строки с большим количеством символов обратного слеша. (Регулярные выражения будут темой обсуждения главы 12.) Это может доставлять определенные неудобства, так как каждый та кой символ придется экранировать: import re phone1 = re.compile("^((?:[(]\\d+[)])?\\s*\\d+(?:\\d+)?)$") Решить эту проблему можно, используя «сырые» (raw) строки. Это обычные строки в кавычках или в тройных кавычках, в которые перед первой кавычкой добавлен символ r. Внутри таких строк все символы интерпретируются как обычные символы, поэтому отпадает необходи мость экранировать символы, которые в других типах строк имеют специальное значение. Ниже приводится регулярное выражение для номера телефона в виде «сырой» строки: phone2 = re.compile(r"^((?:[(]\d+[)])?\s*\d+(?:\d+)?)$") 86 Глава 2. Типы данных Таблица 2.6. Экранированные последовательности в языке Python Если потребуется записать длинный строковый литерал, занимающий две или более строк, но без использования тройных кавычек, то можно использовать один из приемов, показанных ниже: t = "Это не самый лучший способ объединения двух длинных строк, " + \ "потому что он основан на использовании неуклюжего экранирования" s = ("Это отличный способ объединить две длинные строки, " " потому что он основан на конкатенации строковых литералов.") Обратите внимание, что во втором случае для создания единственного выражения мы должны были использовать круглые скобки – без этих скобок переменной s была бы присвоена только первая строка, а нали чие второй строки вызвало бы исключение IndentationError. В руковод стве «Idioms and AntiIdioms», которое можно отыскать в документа ции к языку Python, рекомендуется вместо экранирования перевода строки всегда использовать круглые скобки для объединения операто ров, не умещающихся в одну строку; именно этой рекомендации мы и будем следовать. Последовательность Значение \перевод_строки Экранирует (то есть игнорирует) символ перевода строки \\ Символ обратного слеша (\) \' Апостроф (') \" Кавычка (") \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битовым шестнадцатеричным значением |