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


1350

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

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

    #!/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!"
  2. Кроме того, когда происходит форматирование строки в Python? Например, если мой уровень ведения журнала установлен на ВЫСОКИЙ, я все равно получу удар для выполнения следующей %операции? И если так, есть ли способ избежать этого?

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


2
Для начинающих: вот очень хороший учебник, который учит оба стиля. Я лично %чаще использую старый стиль, потому что, если вам не нужны улучшенные возможности format()стиля, %стиль часто намного удобнее.
Лутц Пречелт



1
Чтобы ответить на ваш второй вопрос, начиная с версии 3.2, вы можете использовать формат {}, если используете пользовательский форматтер (см. Docs.python.org/3/library/logging.html#logging.Formatter )
yanjost

Ответы:


953

Чтобы ответить на ваш первый вопрос ... .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пример выглядит намного чище.

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

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

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


113
как насчет"%(a)s, %(a)s" % {'a':'test'}
Тед

128
Обратите внимание, что вы будете тратить время на, log.debug("something: %s" % x)но не на log.debug("something: %s", x) . Форматирование строк будет обрабатываться в методе, и вы не получите снижение производительности, если оно не будет зарегистрировано. Как всегда, Python предвидит ваши потребности =)
darkfeline

63
Тед: это выглядит хуже, чем делать то же самое '{0}, {0}'.format('test').
летающие овцы

19
Дело в том, что один повторяющийся аргумент о том, что новый синтаксис позволяет переупорядочивать элементы, является спорным: вы можете сделать то же самое со старым синтаксисом. Большинство людей не знают, что это на самом деле уже определено в Ansi C99 Std! Ознакомьтесь с последней копией man sprintfи узнайте о $нотации внутри %заполнителей
cfi

29
@cfi: Если вы хотите что-то наподобие, printf("%2$d", 1, 3)распечатать «3», это указано в POSIX, а не в C99. На самой странице справочника, на которую вы ссылались, написано: «Стандарт C99 не включает стиль, использующий« $ »…».
Танатос

307

То, что оператор по модулю (%) не может сделать, афаик:

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

17
Вы можете использовать форматирование старого стиля mapтак же легко, как и форматирование. map('some_format_string_%s'.__mod__, some_iterable)
2012 г.

3
@cfi: пожалуйста, докажите, что вы правы, переписав приведенный выше пример в C99
MarcH

9
@MarcH: printf("%2$s %1$s\n", "One", "Two");скомпилировано gcc -std=c99 test.c -o test, вывод Two One. Но я исправлюсь: на самом деле это расширение POSIX, а не C. Я не могу найти его снова в стандарте C / C ++, где, как мне казалось, я его видел. Код работает даже с флагом 'c90'. sprintfсправочная страница . Это не перечисляет его, но позволяет библиотекам реализовать суперсет. Мой первоначальный аргумент все еще действителен, заменив CнаPosix
cfi

8
Мой первый комментарий здесь не относится к этому ответу. Я сожалею о фразе. В Python мы не можем использовать оператор %по модулю для переупорядочения заполнителей. Я все еще хотел бы не удалять этот первый комментарий для согласованности комментариев здесь. Я прошу прощения за то, что выразил свой гнев здесь. Он направлен против часто высказываемого заявления о том, что старый синтаксис сам по себе не допускает этого. Вместо того, чтобы создавать совершенно новый синтаксис, мы могли бы ввести расширения std Posix. Мы могли бы иметь оба.
cfi

17
«по модулю» относится к оператору, который оценивает остаток после деления. в этом случае знак процента не является оператором по модулю.
Осьминог

148

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

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

который избегает делать форматирование, если регистратор фактически не регистрирует что-то.


10
Это полезная информация, которую я только что узнал. Жаль, что у него нет своего собственного вопроса, поскольку он кажется отдельным от основного вопроса. Жаль, что ОП не разделил его вопрос на два отдельных вопроса.
snth

12
Вы можете использовать форматирование dict следующим образом: log.debug("some debug info: %(this)s and %(that)s", dict(this='Tom', that='Jerry')) Однако вы не можете использовать новый .format()синтаксис стиля здесь, даже в Python 3.3, что является позором.
Cito

15
@Cito: Смотрите это: plumberjack.blogspot.co.uk/2010/10/…
Vinay Sajip

26
Основным преимуществом этого является не производительность (выполнение строковой интерполяции будет быстрым по сравнению с тем, что вы делаете с выходными данными журналирования, например, отображением в терминале, сохранением на диск). Дело в том, что если у вас есть агрегатор журналирования, он может сказать вам «у вас есть 12 экземпляров этого сообщения об ошибке», даже если все они имели разные значения «some_info». Если форматирование строки выполняется перед передачей строки в log.debug, то это невозможно. Агрегатор может только сказать «у вас было 12 разных сообщений журнала»
Джонатан Хартли,

7
Если вас беспокоит производительность, используйте буквальный синтаксис dict {} вместо создания экземпляров класса dict (): doughellmann.com/2012/11/…
trojjer

119

Начиная с Python 3.6 (2016) вы можете использовать f-строки для замены переменных:

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

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

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


1
Это не отвечает на вопрос. Другой ответ, в котором упоминаются f-строки, по крайней мере, говорит о производительности: stackoverflow.com/a/51167833/7851470
Георгий

60

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


14
Неверно: «Обратную совместимость можно поддерживать, если оставить существующие механизмы на месте». конечно, .formatне заменит % форматирование строки.
Тобиас

12
Нет, постулат BrainStorms верен: «предназначен для замены существующего«% »». Цитата Тобиаса означает, что обе системы будут сосуществовать некоторое время. RTFPEP
фоб

54

Но будьте осторожны, только сейчас я обнаружил один вопрос при попытке заменить все %с .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'

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


12
Нет просто никаких причин менять рабочий код, если formatдействительно не нужны дополнительные функции нового метода ...
Тобиас

Абсолютно согласен с тобой, Тобиас, но иногда это необходимо при обновлении до новых версий Python
wobmene

2
Например? AFAIK, это никогда не было необходимо; Я не думаю, что %интерполяция строк когда-либо исчезнет.
Тобиас

4
Я считаю, что функция .format () безопаснее, чем% для строк. Часто я вижу ошибки начинающих, как это "p1=%s p2=%d" % "abc", 2или "p1=%s p2=%s" % (tuple_p1_p2,). Вы можете подумать, что это ошибка кодера, но я думаю, что это просто странный ошибочный синтаксис, который выглядит хорошо для quicky-scriptie, но плохо для производственного кода.
wobmene

3
Но мне не нравится синтаксис .format (), я был бы счастлив с добрым старым %s, %02dкак "p1=%s p2=%02d".format("abc", 2). Я обвиняю тех, кто изобрел и одобрил форматирование фигурных скобок, которое требует, чтобы вы их избегали, {{}}и выглядит ужасно imho.
wobmene

35

Еще одно преимущество .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 {a.x}, y is {a.y}'.format(a=a)
Out[15]: 'x is 2, y is 3'

Это не возможно с %, насколько я могу судить.


4
Это выглядит более нечитаемо, чем необходимо по сравнению с аналогом 'x is {0}, y is {1}'.format(a.x, a.y). Следует использовать только тогда, когда a.xоперация очень дорогая.
dtheodor

13
@dtheodor С подстройке использовать ключевое слово аргумент вместо позиционных аргументов ... 'x is {a.x}, y is {a.y}'.format(a=a). Более читабельно, чем оба примера.
CivFan

1
@CivFan Или, если у вас есть более одного объекта,'x is {a.x}, y is {a.y}'.format(**vars())
Джек

1
Также обратите внимание на этот в том же образом: '{foo[bar]}'.format(foo={'bar': 'baz'}).
Антуан Пинсард

3
Это невероятно полезно для приложений, ориентированных на клиента, где ваше приложение предоставляет стандартный набор параметров форматирования с предоставленной пользователем строкой формата. Я использую это все время. Например, файл конфигурации будет иметь свойство «messagestring», которое пользователь может предоставить Your order, number {order[number]} was processed at {now:%Y-%m-%d %H:%M:%S}, will be ready at about {order[eta]:%H:%M:%S}или что угодно. Это гораздо чище, чем пытаться предложить ту же функциональность со старым форматером. Это делает пользовательские строки формата более мощными.
Taywee

35

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

Тестовый код:

Python 2.7.2:

import timeit
print 'format:', timeit.timeit("'{}{}{}'.format(1, 1.23, 'hello')")
print '%:', timeit.timeit("'%s%s%s' % (1, 1.23, 'hello')")

Результат:

> format: 0.470329046249
> %: 0.357107877731

Python 3.5.2

import timeit
print('format:', timeit.timeit("'{}{}{}'.format(1, 1.23, 'hello')"))
print('%:', timeit.timeit("'%s%s%s' % (1, 1.23, 'hello')"))

Результат

> format: 0.5864730989560485
> %: 0.013593495357781649

Это выглядит в Python2, разница невелика, тогда как в Python3, %намного быстрее, чемformat .

Спасибо @Chris Cogdon за пример кода.

Изменить 1:

Снова протестирован на Python 3.7.2 в июле 2019 года.

Результат:

> format: 0.86600608
> %: 0.630180146

Там нет большой разницы. Я думаю, что Python постепенно улучшается.

Изменить 2:

После того, как кто-то упомянул в комментарии f-строку Python 3, я провел тест для следующего кода в Python 3.7.2:

import timeit
print('format:', timeit.timeit("'{}{}{}'.format(1, 1.23, 'hello')"))
print('%:', timeit.timeit("'%s%s%s' % (1, 1.23, 'hello')"))
print('f-string:', timeit.timeit("f'{1}{1.23}{\"hello\"}'"))

Результат:

format: 0.8331376779999999
%: 0.6314778750000001
f-string: 0.766649943

Кажется, f-струна все еще медленнее чем, %но лучше чем format.


42
Вместо этого, str.formatдает больше функциональных возможностей (особенно, например, специализированное форматирование '{0:%Y-%m-%d}'.format(datetime.datetime.utcnow())). Производительность не может быть абсолютным требованием всех рабочих мест. Используйте правильный инструмент для работы.
Минхи

36
«Преждевременная оптимизация - корень всего зла», - так однажды сказал Дональд Кнут ...
Ятхарт Агарвал

22
Придерживаться хорошо известной схемы форматирования (при условии, что она удовлетворяет потребностям, что и происходит в подавляющем большинстве случаев) и в два раза быстрее, не является «преждевременной оптимизацией», а просто разумно. Кстати, %оператор позволяет повторно использовать printfзнания; Словарная интерполяция является очень простым расширением принципа.
Тобиас

5
Я действительно испытал противоположное в одной ситуации. Форматирование в новом стиле было быстрее. Можете ли вы предоставить тестовый код, который вы использовали?
Дэвид Сандерс

8
Похоже на серьезно потраченный впустую пост без каких-либо примеров или рассуждений, только заявления.
Кевр

31

Как я обнаружил сегодня, старый способ форматирования строк через %не поддерживает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()метода прямо сейчас.


1
Это возможно потому, что форматирование в новом стиле вызывает str(d)перед расширением параметра, тогда как форматирование в старом стиле, вероятно, вызывает float(d)первым.
Дэвид Сандерс

3
Вы бы так подумали, но str(d)вернулись "3.12375239e-24", а не"0.00000000000000000000000312375239000000000000000000"
Джек

18

Если ваш python> = 3.6, отформатированный в F-string литерал - ваш новый друг.

Это более просто, чисто и лучше.

In [1]: params=['Hello', 'adam', 42]

In [2]: %timeit "%s %s, the answer to everything is %d."%(params[0],params[1],params[2])
448 ns ± 1.48 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

In [3]: %timeit "{} {}, the answer to everything is {}.".format(*params)
449 ns ± 1.42 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

In [4]: %timeit f"{params[0]} {params[1]}, the answer to everything is {params[2]}."
12.7 ns ± 0.0129 ns per loop (mean ± std. dev. of 7 runs, 100000000 loops each)

15

Как примечание, вам не нужно снижать производительность, чтобы использовать новый стиль форматирования с ведением журнала. Вы можете передать любой объект logging.debug, logging.infoи т.д. , который реализует __str__метод волшебной. Когда модуль протоколирования решил, что он должен выдать объект сообщения (каким бы он ни был), он вызывает 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 .


2
Хотелось бы, чтобы я высказался об этом больше. Это позволяет входить в систему formatбез снижения производительности - делает это, переопределяя __str__точно так, как loggingбыло предназначено - сокращает вызов функции до одной буквы ( N), которая очень похожа на некоторые стандартные способы определения строк - И допускает ленивый вызов функции. Спасибо! +1
CivFan

2
Отличается ли это в результате использования logging.Formatter(style='{')параметра?
Давид А

10

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

'{type_names} [a-z]{2}'.format(type_names='triangle|square')

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

'%(type_names)s [a-z]{2}' % {'type_names': 'triangle|square'}

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


3
Или просто использовать '{type_names} [a-z]{{2}}'.format(type_names='triangle|square'). Это как сказать, .format()может помочь при использовании строк, которые уже содержат символ процента. Конечно. Вы должны избежать их тогда.
Alfe

1
@Alfe Вы правы, и поэтому ответ начинается с "One situation where % may help is when you are formatting regex expressions."Конкретно, предположим, что a=r"[a-z]{2}"это кусок регулярного выражения, который вы будете использовать в двух разных конечных выражениях (например, c1 = b + aи c2 = a). Предположим, что c1необходимо formatредактировать (например, bнужно отформатировать время выполнения), но c2это не так. Тогда вам нужно a=r"[a-z]{2}"для c2и a=r"[a-z]{{2}}"для c1.format(...).
Хорхе Лейтао

7

Я хотел бы добавить, что начиная с версии 3.6, мы можем использовать fstrings, как показано ниже

foo = "john"
bar = "smith"
print(f"My name is {foo} {bar}")

Которые дают

Меня зовут джон смит

Все преобразуется в строки

mylist = ["foo", "bar"]
print(f"mylist = {mylist}")

Результат:

mylist = ['foo', 'bar']

Вы можете передать функцию, как в методе других форматов

print(f'Hello, here is the date : {time.strftime("%d/%m/%Y")}')

Давать например

Здравствуйте, вот дата: 16/04/2018



2

Python 3.6.7 сравнительный:

#!/usr/bin/env python
import timeit

def time_it(fn):
    """
    Measure time of execution of a function
    """
    def wrapper(*args, **kwargs):
        t0 = timeit.default_timer()
        fn(*args, **kwargs)
        t1 = timeit.default_timer()
        print("{0:.10f} seconds".format(t1 - t0))
    return wrapper


@time_it
def new_new_format(s):
    print("new_new_format:", f"{s[0]} {s[1]} {s[2]} {s[3]} {s[4]}")


@time_it
def new_format(s):
    print("new_format:", "{0} {1} {2} {3} {4}".format(*s))


@time_it
def old_format(s):
    print("old_format:", "%s %s %s %s %s" % s)


def main():
    samples = (("uno", "dos", "tres", "cuatro", "cinco"), (1,2,3,4,5), (1.1, 2.1, 3.1, 4.1, 5.1), ("uno", 2, 3.14, "cuatro", 5.5),) 
    for s in samples:
        new_new_format(s)
        new_format(s)
        old_format(s)
        print("-----")


if __name__ == '__main__':
    main()

Вывод:

new_new_format: uno dos tres cuatro cinco
0.0000170280 seconds
new_format: uno dos tres cuatro cinco
0.0000046750 seconds
old_format: uno dos tres cuatro cinco
0.0000034820 seconds
-----
new_new_format: 1 2 3 4 5
0.0000043980 seconds
new_format: 1 2 3 4 5
0.0000062590 seconds
old_format: 1 2 3 4 5
0.0000041730 seconds
-----
new_new_format: 1.1 2.1 3.1 4.1 5.1
0.0000092650 seconds
new_format: 1.1 2.1 3.1 4.1 5.1
0.0000055340 seconds
old_format: 1.1 2.1 3.1 4.1 5.1
0.0000052130 seconds
-----
new_new_format: uno 2 3.14 cuatro 5.5
0.0000053380 seconds
new_format: uno 2 3.14 cuatro 5.5
0.0000047570 seconds
old_format: uno 2 3.14 cuatro 5.5
0.0000045320 seconds
-----

3
Вы должны запускать каждый пример несколько раз, один запуск может вводить в заблуждение, например, операционная система обычно занята, поэтому выполнение вашего кода задерживается. см. документы: docs.python.org/3/library/timeit.html . (хороший аватар, Гайбраш!)
jake77

1

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

Пример:

>>> '{{0}, {1}}'.format(1,2)
Traceback (most recent call last):
  File "<pyshell#3>", line 1, in <module>
    '{{0}, {1}}'.format(1,2)
ValueError: Single '}' encountered in format string
>>> '{%s, %s}'%(1,2)
'{1, 2}'
>>> 

2
Вы могли бы сделать это, но я согласен, что это хороший формат {{{0}, {1}}} '. (1, 2)
Сильван ЛЕ ДЕУНФ

Вложенные фигурные скобки ключевого слова работают и симпатичны.
CivFan
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.