Concatenación literal de la cadena Python

Puedo crear una cadena multilínea usando esta syntax:

string = str("Some chars " "Some more chars") 

Esto producirá la siguiente cadena:

 "Some chars Some more chars" 

¿Python se une a estas dos cadenas separadas o el editor / comstackdor las trata como una sola cadena?

Ps: solo quiero entender lo interno. Sé que hay otras formas de declarar o crear cadenas de varias líneas.

Lea el manual de referencia , está ahí . Específicamente:

Se permiten múltiples literales de cadena o bytes adyacentes (delimitados por espacios en blanco), posiblemente utilizando diferentes convenciones de comillas, y su significado es el mismo que su concatenación. Por lo tanto, “hola” ‘mundo’ es equivalente a “helloworld”. Esta función se puede usar para reducir el número de barras invertidas necesarias, para dividir cadenas largas de manera conveniente en líneas largas , o incluso para agregar comentarios a partes de cadenas.

( énfasis mío )

Esta es la razón por:

 string = str("Some chars " "Some more chars") 

es exactamente lo mismo que: str("Some chars Some more chars") .

Esta acción se realiza donde quiera que aparezca un literal de cadena, lista de iniciaciones, llamadas a funciones (como es el caso con la str anterior) y etc.

La única advertencia es cuando un literal de cadena no está contenido entre uno de los delimitadores de agrupación () , {} o [] sino que, en cambio, se propaga entre dos líneas físicas separadas. En ese caso, alternativamente, podemos usar el carácter de barra invertida para unir estas líneas y obtener el mismo resultado:

 string = "Some chars " \ "Some more chars" 

Por supuesto, la concatenación de cadenas en la misma línea física no requiere la barra invertida. ( string = "Hello " "World" está bien)


¿Python se une a estas dos cadenas separadas o el editor / comstackdor las trata como una sola cadena?

Python es, ahora cuando Python hace exactamente esto es donde las cosas se ponen interesantes.

Por lo que pude recostackr ( tomar esto con una pizca de sal, no soy un experto en análisis ), esto sucede cuando Python transforma el árbol de análisis ( LL(1) Parser ) para una expresión dada a su correspondiente AST ( Árbol de syntax abstracta ) .

Puede obtener una vista del árbol analizado a través del módulo parser :

 import parser expr = """ str("Hello " "World") """ pexpr = parser.expr(expr) parser.st2list(pexpr) 

Esto arroja una lista bastante grande y confusa que representa un árbol de syntax concreto analizado a partir de la expresión en expr :

 -- rest snipped for brevity -- [322, [323, [3, '"hello"'], [3, '"world"']]]]]]]]]]]]]]]]]], -- rest snipped for brevity -- 

Los números corresponden a símbolos o tokens en el árbol de análisis y las asignaciones de símbolo a regla gtwigtical y token a constante están en Lib/symbol.py y Lib/token.py respectivamente.

Como puede ver en la versión recortada que agregué, tiene dos entradas diferentes correspondientes a los dos literales str diferentes en la expresión analizada.

A continuación, podemos ver la salida del árbol AST producido por la expresión anterior a través del módulo ast provisto en la Biblioteca Estándar:

 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 = []))])" 

La salida es más fácil de usar en este caso; Puede ver que los args para la llamada a la función es la única cadena concatenada Hello World .

Además, también me topé con un módulo genial que genera una visualización del árbol para los nodos ast . Usándolo, la salida de la expresión expr se visualiza así:

árbol de expresiones para la expresión dada

Imagen recortada para mostrar solo la parte relevante de la expresión.

Como puede ver, en el nodo de la hoja del terminal tenemos un único objeto str , la cadena unida para "Hello " y "World" , es decir, "Hello World" .


Si te sientes lo suficientemente valiente, busca en la fuente, el código fuente para transformar expresiones en un árbol de análisis se encuentra en Parser/pgen.c mientras que el código que transforma el árbol de análisis en un árbol de syntax abstracta se encuentra en Python/ast.c

Esta información es para Python 3.5 y estoy bastante seguro de que, a menos que esté usando una versión realmente antigua ( < 2.5 ), la funcionalidad y las ubicaciones deberían ser similares.

Además, si está interesado en el paso completo de comstackción que Python sigue, uno de los colaboradores principales, Brett Cannon, proporciona una buena introducción suave en el video From Source to Code: How CPython's Compiler Works .