М. Лутц - Изучаем Python (4-е издание)- 2011 (1126907), страница 62
Текст из файла (страница 62)
Спецификатор формата formatspec может также содержать вложенные {} строки форматирования с именамиполей, чтобы извлекать значения из списка аргументов динамически (практически так же, как символ * в операторе форматирования).Подробное описание синтаксиса и полный список допустимых кодов типа вынайдете в руководстве по стандартной библиотеке языка Python – этот списокпрактически полностью совпадает со списком спецификаторов, используемыхв операторе форматирования % и перечисленных в табл. 7.4.
Дополнительно метод format позволяет использовать код типа «b» для отображения целых чиселв двоичном формате (эквивалент вызову встроенной функции bin). Кроме того,код типа «%» используется для отображения символа процента, а для отображения десятичных целых чисел допускается использовать только код «d»(коды «i» и «u» считаются недопустимыми).В следующем примере спецификатор {0:10} предписывает вывести значениепервого позиционного аргумента в поле шириной 10 символов.
Спецификатор242Глава 7. Строки{1:<10} предписывает вывести значение второго позиционного аргумента в полешириной 10 символов, с выравниванием по левому краю, а спецификатор{0.platform:>10} предписывает вывести значение атрибута platform первого позиционного аргумента в поле шириной 10 символов, с выравниванием по правомукраю:>>> ‘{0:10} = {1:10}’.format(‘spam’, 123.4567)‘spam = 123.457’>>> ‘{0:>10} = {1:<10}’.format(‘spam’, 123.4567)‘ spam = 123.457 ‘>>> ‘{0.platform:>10} = {1[item]:<10}’.format(sys, dict(item=’laptop’))‘ win32 = laptop ‘Для вывода вещественных чисел метод format поддерживает те же самые кодытипов и параметры форматирования, что и оператор %.
Так, в следующем примере спецификатор {2:g} предписывает вывести третий аргумент, отформатированный в соответствии с представлением вещественных чисел по умолчанию, предусмотренным кодом «g». Спецификатор {1:.2f} предписывает использовать формат «f» представления вещественных чисел с двумя знаками последесятичной точки, а спецификатор {2:06.2f} дополнительно ограничивает ширину поля вывода 6 символами и предписывает дополнить число нулями слева:>>> ‘{0:e}, {1:.3e}, {2:g}’.format(3.14159, 3.14159, 3.14159)‘3.141590e+00, 3.142e+00, 3.14159’>>> ‘{0:f}, {1:.2f}, {2:06.2f}’.format(3.14159, 3.14159, 3.14159)‘3.141590, 3.14, 003.14’Метод format поддерживает также возможность вывода чисел в шестнадцатеричном, восьмеричном и двоичном представлениях. Фактически строка формата может служить альтернативой использованию некоторых встроенныхфункций:>>> ‘{0:X}, {1:o}, {2:b}’.format(255, 255, 255) # Шестнадцатеричное,‘FF, 377, 11111111’# восьмеричное и двоичное представление>>> bin(255), int(‘11111111’, 2), 0b11111111 # Другие способы работы с (‘0b11111111’, 255, 255)# двоичным представлением>>> hex(255), int(‘FF’, 16), 0xFF # Другие способы работы с(‘0xff’, 255, 255)# шестнадцатеричным представлением>>> oct(255), int(‘377’, 8), 0o377, 0377 # Другие способы работы с(‘0377’, 255, 255, 255)# восьмеричным представлением# 0377 допустимо только в 2.6, но не в 3.0!Параметры форматирования можно указывать непосредственно в строке формата или динамически извлекать из списка аргументов, с помощью синтаксисавложенных конструкций, практически так же, как с помощью символа звездочки в операторе форматирования %:>>> ‘{0:.2f}’.format(1 / 3.0) # Параметры определены непосредственно‘0.33’# в строке формата>>> ‘%.2f’ % (1 / 3.0)‘0.33’>>> ‘{0:.{1}f}’.format(1 / 3.0, 4) # Значение извлекается из списка аргументов243Метод форматирования строк‘0.3333’>>> ‘%.*f’ % (4, 1 / 3.0)‘0.3333’# Как то же самое делается в выраженияхНаконец, в Python 2.6 и 3.0 появилась новая встроенная функция format, которая может использоваться для форматирования одиночных значений.
Онаможет рассматриваться как более компактная альтернатива методу formatи напоминает способ форматирования единственного значения с помощью оператора %:>>> ‘{0:.2f}’.format(1.2345)‘1.23’>>> format(1.2345, ‘.2f’)‘1.23’>>> ‘%.2f’ % 1.2345‘1.23’# Строковый метод# Встроенная функция# Выражение форматированияС технической точки зрения, встроенная функция format вызывает метод __format__ объекта, который в свою очередь вызывает метод str.format каждогоформатируемого элемента.
Однако эта функция имеет не такой компактныйсинтаксис, как оригинальный оператор %, что ведет нас к следующему разделу.Сравнение с оператором форматирования %Если вы внимательно прочитали предыдущие разделы, вы могли заметить,что, по крайней мере, ссылки на позиционные аргументы и ключи словарейв строковом методе format выглядят почти так же, как в операторе форматирования %, особенно когда используются дополнительные параметры форматирования и коды типов значений. В действительности, в общем случае применениеоператора форматирования выглядит проще, чем вызов метода format, особеннопри использовании универсального спецификатора формата %s:print(‘%s=%s’ % (‘spam’, 42))# 2.X+ выражение форматированияprint(‘{0}={1}’.format(‘spam’, 42)) # 3.0 (и 2.6) метод formatКак вы увидите чуть ниже, в более сложных случаях оба способа имеют почтиодинаковую сложность (сложные задачи обычно сложны сами по себе, независимо от используемого подхода), поэтому некоторые считают format в значительной степени избыточным.С другой стороны, метод format предлагает дополнительные потенциальныепреимущества.
Например, оператор % не позволяет использовать именованныеаргументы, ссылки на атрибуты и выводить числа в двоичном представлении,хотя возможность использования словарей в операторе % помогает добиться техже целей. Чтобы увидеть сходные черты между этими двумя приемами, сравните следующие примеры использования оператора % с аналогичными примерами использования метода format, представленными выше:# Основы: с оператором % вместо метода format()>>> template = ‘%s, %s, %s’>>> template % (‘spam’, ‘ham’, ‘eggs’) # Позиционные параметры‘spam, ham, eggs’>>> template = ‘%(motto)s, %(pork)s and %(food)s’>>> template % dict(motto=’spam’, pork=’ham’, food=’eggs’) # Ключи словаря‘spam, ham and eggs’244Глава 7.
Строки>>> ‘%s, %s and %s’ % (3.14, 42, [1, 2])‘3.14, 42 and [1, 2]’# Произвольные типы# Использование ключей, атрибутов и смещений>>> ‘My %(spam)s runs %(platform)s’ % {‘spam’: ‘laptop’, ‘platform’: sys.platform}‘My laptop runs win32’>>> ‘My %(spam)s runs %(platform)s’ % dict(spam=’laptop’, platform=sys.platform)‘My laptop runs win32’>>> somelist = list(‘SPAM’)>>> parts = somelist[0], somelist[-1], somelist[1:3]>>> ‘first=%s, last=%s, middle=%s’ % parts“first=S, last=M, middle=[‘P’, ‘A’]”Когда требуется добиться более сложного форматирования, эти два подходастановятся почти равными в смысле сложности, хотя, если сравнить следующие примеры использования оператора % с аналогичными примерами использования метода format, представленными выше, опять можно заметить, чтооператор % выглядит несколько проще и компактнее:# Специальные приемы форматирования>>> ‘%-10s = %10s’ % (‘spam’, 123.4567)‘spam= 123.4567’>>> ‘%10s = %-10s’ % (‘spam’, 123.4567)‘spam = 123.4567 ‘>>> ‘%(plat)10s = %(item)-10s’ % dict(plat=sys.platform, item=’laptop’)‘win32 = laptop‘# Вещественные числа>>> ‘%e, %.3e, %g’ % (3.14159, 3.14159, 3.14159)‘3.141590e+00, 3.142e+00, 3.14159’>>> ‘%f, %.2f, %06.2f’ % (3.14159, 3.14159, 3.14159)‘3.141590, 3.14, 003.14’# Числа в шестнадцатеричном и восьмеричном представлениях, но не в двоичном>>> ‘%x, %o’ % (255, 255)‘ff, 377’Метод format имеет ряд дополнительных особенностей, которые не поддерживаются оператором %, но даже когда требуется реализовать еще более сложноеформатирование, оба подхода выглядят примерно одинаковыми в смысле сложности.
Например, ниже демонстрируются два подхода к достижению одинаковых результатов – при использовании параметров, определяющих ширинуполей и выравнивание, а также различных способов обращения к атрибутам:# В обоих случаях фактические значения определяются непосредственно в операции>>> import sys>>> ‘My {1[spam]:<8} runs {0.platform:>8}’.format(sys, {‘spam’: ‘laptop’})‘My laptop runs win32’Метод форматирования строк245>>> ‘My %(spam)-8s runs %(plat)8s’ % dict(spam=’laptop’, plat=sys.platform)‘My laptop runs win32’На практике фактические значения редко определяются непосредственнов операции форматирования, как здесь.
Чаще эти значения вычисляются заранее (например, чтобы затем подставить их все сразу в шаблон разметкиHTML�����������������������������������������������������������������). Когда мы начинаем учитывать общепринятую практику в своих примерах, сравнение метода format и оператора % становится еще более наглядным(как вы узнаете в главе 18, аргумент **data в вызове метода – это специальныйсинтаксис распаковывания ключей и значений словарей в отдельные пары«���������������������������������������������������������������������name�����������������������������������������������������������������=����������������������������������������������������������������value�����������������������������������������������������������» именованных аргументов, благодаря чему появляется возможность обращаться к ним по именам в строке формата):# В обоих случаях используются данные, собранные предварительно>>> data = dict(platform=sys.platform, spam=’laptop’)>>> ‘My {spam:<8} runs {platform:>8}’.format(**data)‘My laptop runs win32’>>> ‘My %(spam)-8s runs %(platform)8s’ % data‘My laptop runs win32’Как обычно, сообществу пользователей языка Python еще предстоит решить,что использовать лучше, – оператор %, метод format или их комбинацию.
Поэкспериментируйте с обоими способами самостоятельно, чтобы получить представление об имеющихся возможностях, а за дополнительными подробностями обращайтесь к руководству по стандартной библиотеке Python 2.6 и 3.0.Улучшения метода format в версии Python 3.1: В будущей версии 3.1 (когда писалась эта глава, она находилась еще в состоянии альфа-версии) будет добавлена возможность указыватьсимвол-разделитель разрядов в десятичных числах, что позволит вставлять запятые между трехзначными группами цифр.Для этого достаточно просто добавить запятую перед кодом типазначения, как показано ниже:>>> ‘{0:d}’.format(999999999999)‘999999999999’>>> ‘{0:,d}’.format(999999999999)‘999,999,999,999’Кроме того, в Python 3.1 имеется возможность не указывать явнопорядковые номера позиционных аргументов. В этом случае аргументы из списка будут выбираться последовательно, однакоиспользование этой особенности может свести к нулю основноепреимущество метода format, как это описывается в следующемразделе:>>> ‘{:,d}’.format(999999999999)‘999,999,999,999’>>> ‘{:,d} {:,d}’.format(9999999, 8888888)‘9,999,999 8,888,888’246Глава 7.