Форматирование строки Python:% против .format

Python 2.6 представил метод str.format() с немного отличающимся синтаксисом от существующего оператора % . Что лучше и для каких ситуаций?

  1. Следующее использует каждый метод и имеет тот же результат, так в чем же разница?

  2. Форматирование строки запроса Python SQL
  3. Python добавляет ведущие нули, используя str.format
  4. Формат строки Python: когда использовать флаг конверсии!
  5. Python: запись нескольких вложенных словарей в одной таблице в текстовый файл, разделенный вкладкой
  6. строка в формате python неиспользуемые именованные аргументы
  7. Как мне форматировать число с переменным числом цифр в Python?
  8.  #!/usr/bin/python sub1 = "python string!" sub2 = "an arg" a = "i am a %s" % sub1 b = "i am a {0}".format(sub1) c = "with %(kwarg)s!" % {'kwarg':sub2} d = "with {kwarg}!".format(kwarg=sub2) print a # "i am a python string!" print b # "i am a python string!" print c # "with an arg!" print d # "with an arg!" 
  9. Кроме того, когда форматирование строк происходит в Python? Например, если мой уровень ведения журнала установлен на HIGH, я все равно сделаю удар для выполнения следующей операции % ? И если да, есть ли способ избежать этого?

     log.debug("some debug info: %s" % some_info) 

  • симуляция на основе агентов: проблема с производительностью: Python vs NetLogo & Repast
  • python: создание целых разделов
  • Производительность OrderedDict (по сравнению с deque)
  • Является ли python автоматическим распараллеливанием разделов IO- и CPU- или памяти?
  • Почему программы Python часто медленнее, чем эквивалентная программа, написанная на C или C ++?
  • Самый быстрый способ унифицировать список в Python
  • 11 Solutions collect form web for “Форматирование строки Python:% против .format”

    Чтобы ответить на ваш первый вопрос … .format просто кажется более сложным во многих отношениях. Досадная вещь о % также заключается в том, как она может принимать переменную или кортеж. Вы могли бы подумать, что следующее всегда будет работать:

     "hi there %s" % name 

    однако, если name будет (1, 2, 3) , оно будет бросать TypeError . Чтобы гарантировать, что он всегда печатает, вам нужно будет сделать

     "hi there %s" % (name,) # supply the single argument as a single-item tuple 

    который просто уродлив. .format не имеет этих проблем. Также во втором примере, который вы .format пример .format выглядит намного чище.

    Почему бы вам не использовать его?

    • не зная об этом (мне, прежде чем читать это)
    • должен быть совместим с Python 2.5

    Чтобы ответить на ваш второй вопрос, форматирование строк происходит одновременно с любой другой операцией – при вычислении выражения форматирования строки. И Python, не являясь ленивым языком, оценивает выражения перед вызовом функций, поэтому в вашем примере log.debug выражение "some debug info: %s"%some_info сначала оценивается, например, "some debug info: roflcopters are active" , то эта строка будет передана log.debug() .

    То, что оператор modulo (%) не может сделать, afaik:

     tu = (12,45,22222,103,6) print '{0} {2} {1} {2} {3} {2} {4} {2}'.format(*tu) 

    результат

     12 22222 45 22222 103 22222 6 22222 

    Очень полезно.

    Другой момент: format() , являющийся функцией, может использоваться как аргумент в других функциях:

     li = [12,45,78,784,2,69,1254,4785,984] print map('the number is {}'.format,li) print from datetime import datetime,timedelta once_upon_a_time = datetime(2010, 7, 1, 12, 0, 0) delta = timedelta(days=13, hours=8, minutes=20) gen =(once_upon_a_time +x*delta for x in xrange(20)) print '\n'.join(map('{:%Y-%m-%d %H:%M:%S}'.format, gen)) 

    Результаты в:

     ['the number is 12', 'the number is 45', 'the number is 78', 'the number is 784', 'the number is 2', 'the number is 69', 'the number is 1254', 'the number is 4785', 'the number is 984'] 2010-07-01 12:00:00 2010-07-14 20:20:00 2010-07-28 04:40:00 2010-08-10 13:00:00 2010-08-23 21:20:00 2010-09-06 05:40:00 2010-09-19 14:00:00 2010-10-02 22:20:00 2010-10-16 06:40:00 2010-10-29 15:00:00 2010-11-11 23:20:00 2010-11-25 07:40:00 2010-12-08 16:00:00 2010-12-22 00:20:00 2011-01-04 08:40:00 2011-01-17 17:00:00 2011-01-31 01:20:00 2011-02-13 09:40:00 2011-02-26 18:00:00 2011-03-12 02:20:00 

    Предполагая, что вы используете модуль logging Python, вы можете передать аргументы форматирования строки в качестве аргументов метода .debug() а не самостоятельно выполнять форматирование:

     log.debug("some debug info: %s", some_info) 

    который позволяет избежать форматирования, если регистратор фактически ничего не записывает.

    PEP 3101 предлагает заменить оператора % новым расширенным форматированием строк в Python 3, где он будет использоваться по умолчанию.

    Но будьте осторожны, только сейчас я обнаружил одну проблему при попытке заменить все % на .format в существующем коде: '{}'.format(unicode_string) попытается кодировать unicode_string и, вероятно, сработает.

    Просто посмотрите на этот журнал интерактивных сеансов Python:

     Python 2.7.2 (default, Aug 27 2012, 19:52:55) [GCC 4.1.2 20080704 (Red Hat 4.1.2-48)] on linux2 ; s='й' ; u=u'й' ; s '\xd0\xb9' ; u u'\u0439' 

    s – это просто строка (называемая «байтовый массив» в Python3), а u – строка Unicode (называемая «строка» в Python3):

     ; '%s' % s '\xd0\xb9' ; '%s' % u u'\u0439' 

    Когда вы укажете объект Unicode в качестве параметра для оператора % он выдает строку Unicode, даже если исходная строка не была Unicode:

     ; '{}'.format(s) '\xd0\xb9' ; '{}'.format(u) Traceback (most recent call last): File "<stdin>", line 1, in <module> UnicodeEncodeError: 'latin-1' codec can't encode character u'\u0439' in position 0: ordinal not in range(256) 

    но функция .format поднимет «UnicodeEncodeError»:

     ; u'{}'.format(s) u'\xd0\xb9' ; u'{}'.format(u) u'\u0439' 

    и он будет работать с аргументом Unicode штрафом, только если исходная строка была Unicode.

     ; '{}'.format(u'i') 'i' 

    или если строка аргумента может быть преобразована в строку (так называемый «байтовый массив»)

    Обновление 2016: с Python 3.6 вы можете заменить переменные на строки по имени:

     >>> origin = "London" >>> destination = "Paris" >>> f"from {origin} to {destination}" 'from London to Paris' 

    Обратите внимание на префикс SyntaxError вы попробуете это в Python 3.5 или ранее, вы получите SyntaxError .

    См. https://docs.python.org/3.6/reference/lexical_analysis.html#f-strings

    Еще одно преимущество .format (чего я не вижу в ответах): он может принимать свойства объекта.

     In [12]: class A(object): ....: def __init__(self, x, y): ....: self.x = x ....: self.y = y ....: In [13]: a = A(2,3) In [14]: 'x is {0.x}, y is {0.y}'.format(a) Out[14]: 'x is 2, y is 3' 

    Или, как аргумент ключевого слова:

     In [15]: 'x is {ax}, y is {ay}'.format(a=a) Out[15]: 'x is 2, y is 3' 

    Насколько это возможно.

    Как я обнаружил сегодня, старый способ форматирования строк через % не поддерживает Decimal , модуль Python для десятичной неподвижной точки и арифметики с плавающей запятой, из коробки.

    Пример (с использованием Python 3.3.5):

     #!/usr/bin/env python3 from decimal import * getcontext().prec = 50 d = Decimal('3.12375239e-24') # no magic number, I rather produced it by banging my head on my keyboard print('%.50f' % d) print('{0:.50f}'.format(d)) 

    Вывод:

    0,00000000000000000000000312375239000000009907464850 0,00000000000000000000000312375239000000000000000000

    Разумеется, это могут быть проблемы, но вы все равно можете сразу использовать метод format() .

    В качестве побочного примечания вам не нужно принимать удар производительности, чтобы использовать новое форматирование стиля с протоколированием. Вы можете передать любой объект в logging.debug , logging.info и т. logging.debug , logging.info реализует метод __str__ magic. Когда модуль протоколирования решил, что он должен испускать ваш объект сообщения (независимо от того, что он есть), он вызывает str(message_object) перед этим. Поэтому вы можете сделать что-то вроде этого:

     import logging class NewStyleLogMessage(object): def __init__(self, message, *args, **kwargs): self.message = message self.args = args self.kwargs = kwargs def __str__(self): args = (i() if callable(i) else i for i in self.args) kwargs = dict((k, v() if callable(v) else v) for k, v in self.kwargs.items()) return self.message.format(*args, **kwargs) N = NewStyleLogMessage # Neither one of these messages are formatted (or calculated) until they're # needed # Emits "Lazily formatted log entry: 123 foo" in log logging.debug(N('Lazily formatted log entry: {0} {keyword}', 123, keyword='foo')) def expensive_func(): # Do something that takes a long time... return 'foo' # Emits "Expensive log entry: foo" in log logging.debug(N('Expensive log entry: {keyword}', keyword=expensive_func)) 

    Все это описано в документации Python 3 ( https://docs.python.org/3/howto/logging-cookbook.html#formatting-styles ). Однако он будет работать и с Python 2.6 ( https://docs.python.org/2.6/library/logging.html#using-arbitrary-objects-as-messages ).

    Одно из преимуществ использования этой технологии, помимо того, что она является агностикой в ​​стиле форматирования, заключается в том, что она позволяет использовать ленивые значения, например, функцию expensive_func выше. Это обеспечивает более элегантную альтернативу рекомендациям, приведенным в документах Python: https://docs.python.org/2.6/library/logging.html#optimization .

    % дает намного лучшую производительность, чем format моего теста.

    format работает в два раза медленнее, чем %

    Одна ситуация, когда % может помочь, – это когда вы форматируете выражения регулярных выражений. Например,

     '{type_names} [az]{2}'.format(type_names='triangle|square') 

    вызывает IndexError . В этой ситуации вы можете использовать:

     '%(type_names)s [az]{2}' % {'type_names': 'triangle|square'} 

    Это позволяет писать регулярное выражение как '{type_names} [az]{{2}}' . Это может быть полезно, когда у вас есть два регулярных выражения, где один используется без формата, но конкатенация обоих форматируется.

    Python - лучший язык программирования в мире.