Форматирование цепочки строк в Python - PullRequest
4 голосов
/ 17 июля 2010

Обращаясь с небольшим форматированием SQL, я был поражен, обнаружив, что могу связать форматеры строк:

def get_sql(table, limit=True):
    sql = "select report_date from %s"
    if limit:
        result = "%s limit 1" % sql % table
    else:
        result = sql % table
    return result

Это законно? Есть причина не делать этого?

Ответы [ 4 ]

4 голосов
/ 17 июля 2010

Имеет смысл, что это работает, потому что оператор вроде этого:

'some value goes here %s' % value

Фактически возвращает строку.Вероятно, более логично смотреть на это так:

result = ("%s limit 1" % sql) % table

В этом нет ничего особенного, но операторы цепочки могут привести к проблемам с выяснением, откуда возникла ошибка.

Так, например, это работает нормально:

>>> sql = 'a value of %s'
>>> x = 'some string %s with stuff'
>>> y = 'VALUE'
>>> x % sql % y
'some string a value of VALUE with stuff'

Но если там была ошибка форматирования (я понимаю, что этот пример патологичен, но он все понял):

>>> sql = 'a value of %d'
>>> x = 'some string %d with stuff'
>>> y = 123    
>>> x % sql % y
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: %d format: a number is required, not str

Не совсем понятно, какая %d вызывает вашу ошибку.По этой причине я бы разделил его и просто использовал один форматер % на строку, если это возможно, потому что тогда трассировка сможет указать вам, какая именно строка и какой форматтер имели проблему.

Длязапишите, выполнив один форматер на строку, вы также значительно упростите жизнь тем, кто читает ваш код и пытается выяснить, что происходит.

3 голосов
/ 17 июля 2010

Это совершенно законно.

Форма строкового форматера " single аргумент " действительно является особым случаем - для нескольких элементов обычно используется кортеж, и это привело бы к более очевидному примеру того, почему это нормально

result = "%s limit 1" % (sql % (table,),)

Первоначально этот ^ был написан, чтобы убедить спрашивающего, что поддержка нескольких форматов была законной языковой функцией, но, как комментирует Нас Банов, он читается так, будто я пытаюсь объяснить, как это работает(не помогло облажаться код).Он не строит строку справа налево, как это предполагает, что это возможно, но ДОЛЖЕН строить ее (быть ассоциативным) слева направо.Оператор должен взять строку слева и вернуть ее, но может взять не строку (кортеж) справа.Поскольку вы не можете использовать% на паре кортежей, он не может работать в обратном порядке

>>> "%s %f %s" % ( "%d", 0.1, "%d %d" ) % (1,2,3)
'1 0.100000 2 3'

Это может, однако, привести к сложному / грязному коду, поэтому лично я бы использовал егоочень экономно.

Вы могли бы проработать свой пример так:

def get_sql(table, limit=True):
    sql = "select report_date from"
    strlimit = ""
    if limit:
        strlimit = "limit 1"
    return "%s %s"%(sql, strlimit)
2 голосов
/ 17 июля 2010

Почему, да, возможно цепное форматирование строки% таким образом, даже если это первый раз, когда я вижу, что он используется (и ужасным образом, учтите)!

Причина в том, что операторы одного типа group left to right (имеют "левую ассоциативность" - с заметными исключениями возведения в степень ** и сравнения a<b<c).

Так же, как и

>>> 1 - 2 - 3    # equals to (1-2)-3
-4
>>> 16 / 4 / 2   # equals to (16 /4) /2,  NOT 16 / (4 / 2)
2

также s1 % s2 % s3 равно (s1 % s2) % s3

Да, и, кстати, не имеет значения, являются ли s1, s2 и s3 строками или числами - компилятор не знает, что во время компиляции, и только во время выполнения будет определено, означает ли % «остаток от деления» (если s1 - число) или форматирование строки (если s1 - строка).

0 голосов
/ 17 июля 2010

Я бы написал так:

def get_sql(table,limit=True):
    sql = "select report_date from %s"%table
    if limit: sql += " limit 1"
    return sql

PS.Код, который вы опубликовали, работает так:

In [49]: "%s limit 1" % sql
Out[49]: 'select report_date from %s limit 1'

In [50]: "%s limit 1" % sql % 'table'
Out[50]: 'select report_date from table limit 1'

Конечно, вы можете это сделать, но я не думаю, что это особенно понятно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...