Конкретная конкатенация строк Python
Я могу создать многострочную строку, используя этот синтаксис:
string = str("Some chars "
"Some more chars")
Это создаст следующую строку:
"Some chars Some more chars"
Python соединяет эти две отдельные строки или редактор / компилятор рассматривает их как одну строку?
Ps: я просто хочу понять внутренности. Я знаю, что есть и другие способы объявления или создания многострочных строк.
1 ответ
Прочитайте справочное руководство, оно там. В частности:
Допускается использование нескольких смежных строковых или байтовых литералов (разделенных пробелами), возможно, с использованием различных соглашений о цитировании, и их значение совпадает с их конкатенацией. Таким образом, "привет" "мир" эквивалентен "helloworld". Эта функция может быть использована для уменьшения необходимого количества обратных слэшей, для удобного разделения длинных строк на длинные или даже для добавления комментариев к частям строк.
(акцент мой)
Вот почему:
string = str("Some chars "
"Some more chars")
точно так же, как: str("Some chars Some more chars")
,
Это действие выполняется везде, где может появляться строковый литерал, инициализация списка, вызовы функций (как в случае с str
выше) и так далее.
Единственное предостережение - когда строковый литерал не содержится между одним из разделителей группировки. ()
, {}
или же []
но вместо этого распространяется между двумя отдельными физическими линиями. В этом случае мы можем альтернативно использовать символ обратной косой черты, чтобы соединить эти строки и получить тот же результат:
string = "Some chars " \
"Some more chars"
Конечно, объединение строк в одной физической строке не требует обратной косой черты. (string = "Hello " "World"
просто отлично)
Python соединяет эти две отдельные строки или редактор / компилятор рассматривает их как одну строку?
Python, теперь, когда именно Python делает это, все становится интересным.
Из того, что я мог бы собрать (взять это с щепоткой соли, я не эксперт разбора), это происходит, когда Python преобразует дерево разбора (LL(1)
Parser) для данного выражения к соответствующему AST ( абстрактному синтаксическому дереву).
Вы можете получить представление о разобранном дереве через parser
модуль:
import parser
expr = """
str("Hello "
"World")
"""
pexpr = parser.expr(expr)
parser.st2list(pexpr)
Это выводит довольно большой и запутанный список, который представляет конкретное синтаксическое дерево, проанализированное из выражения в expr
:
-- rest snipped for brevity --
[322,
[323,
[3, '"hello"'],
[3, '"world"']]]]]]]]]]]]]]]]]],
-- rest snipped for brevity --
Числа соответствуют либо символам, либо токенам в дереве разбора, а сопоставления от символа к правилу грамматики и токена к константе находятся в Lib/symbol.py
а также Lib/token.py
соответственно.
Как вы можете видеть в отредактированной версии, которую я добавил, у вас есть две разные записи, соответствующие двум разным str
литералы в выражении разбираются.
Далее мы можем просмотреть вывод дерева AST, созданного предыдущим выражением, через ast
Модуль предоставлен в стандартной библиотеке:
p = ast.parse(expr)
ast.dump(p)
# this prints out the following:
"Module(body = [Expr(value = Call(func = Name(id = 'str', ctx = Load()), args = [Str(s = 'hello world')], keywords = []))])"
В этом случае вывод более удобен для пользователя; Вы можете видеть, что args
для вызова функции - единственная каскадная строка Hello World
,
Кроме того, я также наткнулся на классный модуль, который генерирует визуализацию дерева для ast
узлы. Используя его, вывод выражения expr
визуализируется так:
Изображение обрезано, чтобы показать только соответствующую часть для выражения.
Как вы можете видеть, в терминальном конечном узле у нас есть один str
объект, объединенная строка для "Hello "
а также "World"
т.е. "Hello World"
,
Если вы чувствуете себя достаточно смелым, покопайтесь в исходном коде, исходный код для преобразования выражений в дерево разбора находится по адресу Parser/pgen.c
в то время как код, преобразующий дерево синтаксического анализа в абстрактное синтаксическое дерево, находится в Python/ast.c
,
Эта информация для Python 3.5
и я уверен, что если вы не используете действительно старую версию (< 2.5
) функциональность и расположение должны быть одинаковыми.
Кроме того, если вас интересует весь этап компиляции, за которым следует python, то один из основных участников, Бретт Кэннон (Brett Cannon), предоставит хорошее мягкое введение в видео " Из исходного кода в код: как работает компилятор CPython".