Что делает звезда (звездочка) в струнной?
В документе python 2.4.3. Отформатированные строковые литералы, кажется возможным написать звезду, за которой следует выражение в f-строке {}
, но я не могу найти, как это использовать.
Что это и как я могу это использовать? Это где-то задокументировано?
Чтобы быть точным, это касается "*" or_expr
части следующего BNF.
f_string ::= (literal_char | "{{" | "}}" | replacement_field)*
replacement_field ::= "{" f_expression ["!" conversion] [":" format_spec] "}"
f_expression ::= (conditional_expression | "*" or_expr)
("," conditional_expression | "," "*" or_expr)* [","]
| yield_expression
Я попробовал это в REPL, но это вызывает ошибку.
>>> l = [1, 2, 3]
>>> f"{l}"
'[1, 2, 3]'
>>> f"{*l}"
File "<stdin>", line 1
SyntaxError: can't use starred expression here
Ответы
Ответ 1
Существует две альтернативы для f_expression
: разделенный запятыми список or_expression
s, перед которыми необязательно or_expression
звездочки, или одиночное yield_expression
. Обратите внимание, что yield_expression
не позволяет использовать звездочку.
Я предполагаю, что намерение состояло в том, что альтернатива списка через запятую выбирается только тогда, когда есть хотя бы одна запятая, но на самом деле грамматика этого не говорит. Я чувствую, что оператор повторения в конце должен был быть +
вместо *
.
Так что f"{*1}"
будет синтаксической ошибкой, потому что есть звездочка, но без запятой. f"{*1,*2}"
синтаксически допустимо, но ошибка типа, потому что 1 и 2 не повторяемы. f"{*[1], *[2]}"
является действительным и действует так же, как f"{1,2}"
. Таким образом, звездочка разрешена, потому что она действует как оператор splat в кортежах, которые могут быть записаны без скобок в f-выражениях.
Обратите внимание, что использование or_expr
в качестве операнда для *
не означает, что там должен использоваться побитовый оператор или - он просто означает, что побитовый оператор или является первым оператором в иерархии предшествования, который будет разрешен в качестве операнда для *
Так что это просто установка приоритета префикса *
сравнению с другими выражениями. Я полагаю, что or_expression
последовательно используется как операнд для префикса *
везде в грамматике (то есть везде, где за префиксом *
следует выражение, а не имя параметра).
Ответ 2
Насколько я знаю, вы можете использовать в контексте функции внутри f
строки.
Вот рабочий пример:
def do_print(*l):
return l
print(f"{do_print(*(1, 2, 3))}")
Это распечатывает:
(1, 2, 3)
тогда как, если вы попробуете:
print(f"{do_print((1, 2, 3))}")
вы получите этот вывод:
((1, 2, 3),)
Одиночная звезда * распаковывает tupe в позиционные аргументы функции и может использоваться внутри вызова внутри строки f
.
Другой пример:
def sum(a, b):
return a + b
print(f"{sum(*(1, 2))}")
Ответ 3
Ясно, что "*"
не означает, что вы можете использовать оператор *
или, по крайней мере, это не то, что они намеревались сказать. Если вам разрешено использовать помеченное выражение или помеченный элемент напрямую, это было бы явно упомянуто с одной из следующих нотаций.
expression_list ::= expression ("," expression)* [","]
starred_list ::= starred_item ("," starred_item)* [","]
starred_expression ::= expression | (starred_item ",")* [starred_item]
starred_item ::= expression | "*" or_expr
Как видите, "*" or_expr
является частью грамматики starred_item
которая не имеет никакого смысла, потому что вы можете использовать любую двоичную f_string
операцию в f_string
. Я думаю, что это скорее ошибка документации, чем ошибка в коде.
Отказ от ответственности:
Даже если or_expr
является идентификатором для expr
который из-за ссылок на ссылки в doc очень запутан и явно ошибочен, он все равно является ошибкой в документации, поскольку, во-первых, он не соответствует поведению исходного кода, а во-вторых, зачем использовать *expr
вместо правильных помеченных обозначений выражений с меньшей неопределенностью.
Я отправил вопрос здесь https://bugs.python.org/msg341187. Я надеюсь, что это может помочь выяснить проблему для нас.
Ответ 4
Посмотрите здесь: https://realpython.com/python-f-strings/. У них есть большой список новых способов, которыми Python поддерживает форматирование строк. Честно говоря, никогда в жизни не видел такого рода звездочек. Может быть, это что-то новое. Надеюсь, поможет.
Ответ 5
Я не думаю, что *
f-string
должна использоваться для списка, более вероятно, что она будет использоваться для умножения
In [81]: f"{5*2}"
Out[81]: '10'
Ответ 6
Я не хочу искажать ваш вопрос здесь, но у меня есть то, что я считаю наиболее разумным ответом.
Если вы посмотрите на этот вопрос, им будет интересно, почему они не могут отформатировать строку, используя синтаксис %
как показано ниже.
>>> l = [1, 2, 3]
>>> "%d" % *l
File "<stdin>", line 1
SyntaxError: can't use starred expression here
По сути, я собираю, что слишком много ценностей для распаковки, но не так, как вы думаете. Видите, в f-строке {...}
ожидается одно значение, и, передав коллекцию и пытаясь распаковать ее одновременно (даже если коллекция имеет только одно значение, я попытался ради здравого смысла) Python кричит на вас потому что вы будете передавать несколько значений чему-то ожидающему только одно.
То, что у меня есть для вас, это альтернативный метод. Это не так красиво, как использование звездочки *
, но результат такой же, как и ожидалось.
>>> l = [1, 2, 3]
>>> f"{', '.join(map(str, l))}"
'1, 2, 3'
Печать упрощает работу, но все должно выполняться вручную при форматировании строки