Руководство по форматированию строк с помощью Python
Оглавление
Форматирование строк является надежной и мощной частью инструментария любого программиста на Python - почти каждая часть производственного программного обеспечения так или иначе использует его преимущества. Однако средства форматирования строк сильно изменились за время существования Python. От форматирования %
, метода format()
до форматированных строковых литералов - возможности форматирования строк не ограничены.
Компоновка формы и содержания строк во время выполнения - это базовая возможность любого языка высокого уровня. Вставляете ли вы значения переменных в сообщение журнала, формируете вывод на основе пользовательского ввода или создаете сообщения для клиента с использованием временной метки - вам часто понадобится эта функция. На базовом уровне вы можете конкатенировать строки, просто используя +
, но это неэффективно, а также трудно сделать выразительным. Именно здесь на помощь приходят возможности Python по форматированию строк.
Старый способ: printf
стилевое форматирование.
Один из первоначальных способов форматирования строк в Python был основан на соглашении, используемом в printf. Вставка значения в строку осуществлялась путем представления его в виде %, за которым следовал символ, указывающий на его тип. Итак, для вставки строки и целого числа:
>>> this = "this"
>>> five = 5
>>> "%s is a %d" % (this, five)
'this is a 5'
%d
вызовет ошибку типа TypeError
, если входные данные не являются целым числом. %s
- это то же самое, что и вызов str()
на входе. Это можно использовать с любым объектом, а не только со строками:
>>> "%s is a list" % [1,2,3]
'[1, 2, 3] is a list'
%r
- это то же самое, что вызов repr()
на вход, в отличие от %s
:
>>> "%s sounds like %r" % ("Seaweed", "Seaweed")
"Seaweed sounds like 'Seaweed'"
При использовании плавающих цифр количество отображаемых цифр можно контролировать путем вставки этого числа:
>>> "%.3f" % 6.1234567
'6.123'
Обратите внимание, что при усечении цифр значение не округляется. Для добавления вставки к строкам добавьте количество вставки следующим образом:
>>> for w in ['some', 'words', 'are', 'longer']:
... print("|%15s" % w)
...
| some
| words
| are
| longer
Словарь также можно использовать для вставки значений в строку:
>>> ship_info = {'ship': 'personiples', 'captain': 'Archaeus'}
>>> "%(ship)s was run hard by %(captain)s" % ship_info
'personiples was run hard by Archaeus'
Основные недостатки стиля printf
заключаются в том, что в нем очень легко допустить ошибки, что он может быть ограничен в количестве передаваемых аргументов, а также он не так интуитивен и выразителен, как более современные инновации.
Python 3: str.format()
В Python 3 был представлен новый способ форматирования строк: метод str.format()
, использующий мини-язык спецификации формата, который предлагал более мощное форматирование. Это было перенесено в Python 2.6.
В этой новой спецификации для указания полей замены используются фигурные скобки, а не %s
В стиле %
. Позиция аргументов определяет позицию в целевой строке, что может быть сделано и в стиле str.format()
:
>>> "{} comes before {}".format('a','b')
'a comes before b'
Теперь мы можем также указать индекс аргумента, что позволяет повторять и менять порядок исходных аргументов:
>>> "{1} is after {0} which is before {1}".format('a','b')
'b is after a which is before b'
Еще более интересной является возможность доступа к аргументам по имени:
>>> "{cat} loves {dog}, {dog} loves {cat}".format(cat='Whiskers', dog='Rover')
'Whiskers loves Rover, Rover loves Whiskers'
Этот механизм можно использовать в сочетании со словарями:
>>> ship_captains = {'The Irish Rover': 'Mick McCann', 'Davey Crockett': 'Burgess'}
>>> "{Davey Crockett} and {The Irish Rover} are both ship captains".format(**ship_captains)
'Burgess and Mick McCann are both ship captains'
Поле замены может содержать любое выражение, включая доступ к атрибутам объекта:
>>> class Ship:
... def __init__(self, name, masts, captain):
... self.name = name
... self.masts = masts
... self.captain = captain
...
... def __str__(self):
... msg = "{self.name} had {self.masts} masts and was captained by {self.captain}"
... return msg.format(self=self)
...
>>> ships = [ Ship("The Irish Rover", 27, 'Mick McCann'),
... Ship("Davey Crockett", 3, 'Burgess'),
... Ship("The John B", 2, 'Richard Le Gallienne') ]
>>>
>>> for ship in ships:
... print(ship)
...
The Irish Rover had 27 masts and was captained by Mick McCann
Davey Crockett had 3 masts and was captained by Burgess
The John B had 2 masts and was captained by Richard Le Gallienne
Наконец, мы можем добавить аргументы спецификации формата после имени поля или индекса - например, для выравнивания мы можем использовать >
или <
, за которыми следует желаемый padding:
>>> for ship in ships:
... print("|{ship.name:>22}|{ship.captain:>22}|{ship.masts:>22}|".format(ship=ship))
...
| The Irish Rover| Mick McCann| 27|
| Davey Crockett| Burgess| 3|
| The John B| Richard Le Gallienne| 2|
Новый стандарт: f-строки (f-string)
Хотя метод str.format менее подвержен ошибкам, чем стиль printf, он все же не является наиболее интуитивно понятным для использования. Гораздо более читабельным и интуитивно понятным решением является использование f-строк. Форматированные строковые литералы, или f-строки, были введены в Python 3.6 и являются интересным дополнением к нашему арсеналу. Они обозначаются символами f
или F
перед открывающей кавычками строкой. Они позволяют нам использовать те же поля замены, что и str.format()
, но при этом выражения в этих полях будут находиться в текущей среде, а не передаваться в метод format.
>>> strings_count = 5
>>> frets_count = 21
>>> f"My banjo has {strings_count} strings and {frets_count} frets"
'My banjo has 5 strings and 21 frets
Здесь видно, что мы сослались на переменные strings_count
и frets_count
внутри f-строки. Мы можем использовать выражения, которые обращаются к содержимому списка в полях замены:
>>> arrivals = ['The Irish Rover', 'The Titanic', 'The Rueben']
>>> f'The first to arrive was {arrivals[0]} and the last was {arrivals[-1]}'
'The first to arrive was The Irish Rover and the last was The Rueben'
За выражением следует поле преобразования, представленное типом преобразования, которому предшествует символ !
. Чтобы использовать форму repr()
в строке, используйте поле преобразования !r
:
>>> ship_name = "Davey Crockett"
>>> f'The ships name was spelled {ship_name!r}'
"The ships name was spelled 'Davey Crockett'"
Это то же самое, что вызвать repr()
напрямую:
>>> f'The ships name was spelled {repr(ship_name)}'
"The ships name was spelled 'Davey Crockett'"
Также существует тип преобразования для функции ascii()
:
>>> check = “√”
>>> f"The ascii version of {check} is {check!a}"
"The ascii version of √ is '√'"
Мы также можем вложить поля:
>>> rag_count = 1000000
>>> padding = 10
>>> f'Sligo rags: {rag_count:{padding}d}'
'Sligo rags: 1000000'
В этой заметке мы лишь поверхностно рассмотрели некоторые возможности форматирования строк в Python. Возможности и выбор, доступные при использовании различных вариантов форматирования строк, дают любому программисту на Python огромное количество вариантов форматирования строк так, как вы хотите.
С появлением F-строк у нас появилось мощное, интуитивно понятное и читаемое решение. Программистам на python, которые хотят узнать больше, я бы посоветовал посмотреть документацию по мини-языку format string и открыть оболочку, чтобы попробовать f-строки с различными вариантами формата - это действительно интересное и мощное нововведение.
Вернуться на верх