7. Declaraciones simples¶
Una declaración simple se compone dentro de una sola línea lógica. Pueden producirse varias declaraciones simples en una sola línea separada por punto y coma. La sintaxis de las declaraciones simples es:
simple_stmt ::=expression_stmt
|assert_stmt
|assignment_stmt
|augmented_assignment_stmt
|annotated_assignment_stmt
|pass_stmt
|del_stmt
|return_stmt
|yield_stmt
|raise_stmt
|break_stmt
|continue_stmt
|import_stmt
|future_stmt
|global_stmt
|nonlocal_stmt
7.1. Declaraciones de tipo expresión¶
Las declaraciones de tipo expresión son usadas (en su mayoría interactivamente) para computar y escribir un valor, o (usualmente) para llamar a un método (una función que no retorna un resultado significativo; en Python, los métodos retornan el valor None
). Otros usos de las declaraciones de tipo expresión son permitidas y ocasionalmente útiles. La sintaxis para una declaración de tipo expresión es:
expression_stmt ::= starred_expression
Una declaración de tipo expresión evalúa la lista de expresiones (que puede ser una única expresión).
En modo interactivo, si el valor no es None
, es convertido a cadena de caracteres usando la función built-in repr()
y la cadena resultante es escrita en la salida estándar en una línea por si sola (excepto si el resultado es None
, entonces el procedimiento llamado no produce ninguna salida.)
7.2. Declaraciones de asignación¶
Las declaraciones de asignación son usadas para (volver a) unir nombres a valores y para modificar atributos o elementos de objetos mutables:
assignment_stmt ::= (target_list
"=")+ (starred_expression
|yield_expression
) target_list ::=target
(","target
)* [","] target ::=identifier
| "(" [target_list
] ")" | "[" [target_list
] "]" |attributeref
|subscription
|slicing
| "*"target
(Ver sección Primarios para las definiciones de sintaxis para attributeref, subscription, y slicing.)
Una declaración de asignación evalúa la lista de expresiones (recuerda que ésta puede ser una única expresión o una lista separada por comas, la última produce una tupla) y asigna el único objeto resultante a cada una de las listas de objetivos, de izquierda a derecha.
Las asignaciones son definidas recursivamente dependiendo de la forma del objetivo (lista). Cuando el objetivo es parte de un objeto mutable (una referencia a un atributo, una subscripción o un segmento), el objeto mutable finalmente debe realizar la asignación y decidir sobre su validez, y puede lanzar una excepción si la asignación no es aceptable. Las reglas observadas por varios tipos y las excepciones lanzadas se dan con la definición de los tipos de objeto (ver sección Jerarquía de tipos estándar).
La asignación de un objeto a una lista de destino, opcionalmente entre paréntesis o corchetes, se define de forma recursiva de la siguiente manera.
Si la lista de destino es un único objeto sin terminar en coma, opcionalmente entre paréntesis, el objeto es asignado a ese objetivo.
Else:
Si la lista de objetivos contiene un objetivo prefijado con un asterisco, llamado objetivo “destacado”: El objeto debe ser iterable con al menos tantos elementos como objetivos en la lista de objetivos, menos uno. Los primeros elementos del iterable se asignan, de izquierda a derecha, a los objetivos antes del objetivo destacado. Los elementos finales del iterable se asignan a los objetivos después del objetivo destacado. Luego se asigna una lista de los elementos restantes en el iterable al objetivo destacado (la lista puede estar vacía).
Sino: el objeto debe ser iterable con el mismo número de elementos que los elementos en la lista de objetivos, y los elementos son asignados a sus respectivos objetivos de izquierda a derecha.
La asignación de un objeto a un único objetivo se define a continuación de manera recursiva.
Si el objetivo es un identificador (nombre):
Si el nombre no ocurre en una declaración
global
ononlocal
en el actual bloque de código: el nombre es unido al objeto del actual espacio de nombres local.Por otra parte: el nombre es unido al objeto en el nombre de espacio global o el nombre de espacio exterior determinado por
nonlocal
, respectivamente.
El nombre se vuelve a unir si ya ha estado unido. Esto puede hacer que el recuento de referencia para el objeto previamente vinculado al nombre llegue a cero, provocando que el objeto se desasigne y se llame a su destructor (si tiene uno).
Si el destino es una referencia de atributo: se evalúa la expresión primaria en la referencia. Debe producir un objeto con atributos asignables; si este no es el caso, una excepción
TypeError
es lanzada. Luego se le pide a ese objeto que asigne el objeto asignado al atributo dado; si no puede realizar la tarea, lanza una excepción (generalmente pero no necesariamenteAttributeError
).Nota: Si el objeto es una instancia de clase y la referencia de atributo ocurre en ambos lados del operador de asignación, la expresión del lado derecho,
a.x
puede acceder a un atributo de instancia o (si no existe un atributo de instancia) a una clase atributo. El objetivo del lado izquierdoa.x
siempre se establece como un atributo de instancia, creándolo si es necesario. Por lo tanto, las dos ocurrencias dea.x
no necesariamente se refieren al mismo atributo: si la expresión del lado derecho se refiere a un atributo de clase, el lado izquierdo crea un nuevo atributo de instancia como el objetivo de la asignación:class Cls: x = 3 # class variable inst = Cls() inst.x = inst.x + 1 # writes inst.x as 4 leaving Cls.x as 3
Esta descripción no se aplica necesariamente a los atributos del descriptor, como las propiedades creadas con
property()
.Si el objetivo es una suscripción: se evalúa la expresión primaria en la referencia. Debe producir un objeto de secuencia mutable (como una lista) o un objeto de mapeo (como un diccionario). A continuación, se evalúa la expresión del subíndice.
Si el primario es un objeto de secuencia mutable (como una lista), el subíndice debe producir un número entero. Si es negativo, se le suma la longitud de la secuencia. El valor resultante debe ser un número entero no negativo menor que la longitud de la secuencia, y se le pide a la secuencia que asigne el objeto asignado a su elemento con ese índice. Si el índice está fuera de rango,
IndexError
se lanza (la asignación a una secuencia suscrita no puede agregar nuevos elementos a una lista).Si el principal es un objeto de mapeo (como un diccionario), el subíndice debe tener un tipo compatible con el tipo de clave del mapeo, y luego se le pide al mapeo que cree un par clave / dato que mapee el subíndice al objeto asignado. Esto puede reemplazar un par clave / valor existente con el mismo valor clave o insertar un nuevo par clave / valor (si no existía ninguna clave con el mismo valor).
Para objetos definidos por el usuario, se llama al método
__setitem__()
con los argumentos apropiados.Si el destino es un rebanado (slicing): la expresión principal de la referencia es evaluada. Debería producir un objeto de secuencia mutable (como una lista). El objeto asignado debe ser un objeto de secuencia del mismo tipo. A continuación, se evalúan las expresiones de límite superior e inferior, en la medida en que estén presentes; los valores predeterminados son cero y la longitud de la secuencia. Los límites deben evaluarse a números enteros. Si alguno de los límites es negativo, se le suma la longitud de la secuencia. Los límites resultantes se recortan para que se encuentren entre cero y la longitud de la secuencia, inclusive. Finalmente, se solicita al objeto de secuencia que reemplace el segmento con los elementos de la secuencia asignada. La longitud del corte puede ser diferente de la longitud de la secuencia asignada, cambiando así la longitud de la secuencia objetivo, si la secuencia objetivo lo permite.
Detalles de implementación de CPython: En la implementación actual, se considera que la sintaxis de los objetivos es la misma que la de las expresiones y se rechaza la sintaxis no válida durante la fase de generación del código, lo que genera mensajes de error menos detallados.
Aunque la definición de asignación implica que las superposiciones entre el lado izquierdo y el lado derecho son ‘simultáneas’ (por ejemplo, a, b = b, a
intercambia dos variables), las superposiciones dentro de la colección de las variables asignadas ocurren de izquierda a derecha, lo que a veces genera confusión. Por ejemplo, el siguiente programa imprime [0, 2]
:
x = [0, 1]
i = 0
i, x[i] = 1, 2 # i is updated, then x[i] is updated
print(x)
Ver también
- PEP 3132 - Desembalaje Iterable Extendido
La especificación para la función
*target
.
7.2.1. Declaraciones de asignación aumentada¶
La asignación aumentada es la combinación, en una sola declaración, de una operación binaria y una declaración de asignación:
augmented_assignment_stmt ::=augtarget
augop
(expression_list
|yield_expression
) augtarget ::=identifier
|attributeref
|subscription
|slicing
augop ::= "+=" | "-=" | "*=" | "@=" | "/=" | "//=" | "%=" | "**=" | ">>=" | "<<=" | "&=" | "^=" | "|="
(Ver sección Primarios para la definición de la sintaxis de los tres últimos símbolos.)
Una asignación aumentada evalúa el destino (que, a diferencia de las declaraciones de asignación normales, no puede ser un desempaquetado) y la lista de expresiones, realiza la operación binaria específica del tipo de asignación en los dos operandos y asigna el resultado al destino original. El objetivo sólo se evalúa una vez.
Una declaración de asignación aumentada como x += 1
puede ser reescriba como x = x + 1
para alcanzar un efecto similar pero no exactamente igual. En la versión aumentada, x
es evaluada una única vez. Además, cuando es posible, la operación real se realiza in-place, lo que significa que en lugar de crear un nuevo objeto y asignarlo al objetivo, el objeto anterior se modifica.
A diferencia de las asignaciones normales, las asignaciones aumentadas evalúan el lado izquierdo antes de evaluar el lado derecho. Por ejemplo, a[i] += f(x)
primero busca a[i]
, entonces evalúa f(x)
y realiza la suma, y finalmente, vuelve a escribir el resultado en a[i]
.
Con la excepción de la asignación a tuplas y múltiples objetivos en una sola instrucción, la asignación realizada por las instrucciones de asignación aumentada se maneja de la misma manera que las asignaciones normales. De manera similar, con la excepción del posible comportamiento in situ, la operación binaria realizada por la asignación aumentada es la misma que las operaciones binarias normales.
Para destinos que son referencias a atributos, lo mismo que caveat about class and instance attributes se aplica para asignaciones regulares.
7.2.2. Declaraciones de asignación anotadas¶
Asignación Annotation es la combinación, en una única declaración, de una variable o anotación de atributo y una declaración de asignación opcional:
annotated_assignment_stmt ::=augtarget
":"expression
["=" (starred_expression
|yield_expression
)]
The difference from normal Declaraciones de asignación is that only a single target is allowed.
Para nombres simples como destinos de asignación, si están en el ámbito de clase o módulo, las anotaciones se evalúan y almacenan en una clase especial o atributo de módulo __annotations__
que es una asignación de diccionario de nombres de variables (alterados si son privados) a anotaciones evaluadas. Este atributo se puede escribir y se crea automáticamente al comienzo de la ejecución del cuerpo del módulo o la clase, si las anotaciones se encuentran estáticamente.
Para expresiones como destinos de asignaciones, las anotaciones se evalúan si están en ámbitos de clase o módulo pero no se almacenan.
Si se anota un nombre en el ámbito de una función, este nombre es local para ese ámbito. Las anotaciones nunca se evalúan y almacenan en ámbitos de función.
Si el lado derecho está presente, una tarea anotada realiza la tarea real antes de evaluar las anotaciones (cuando corresponda). Si el lado derecho no está presente para un destino de expresión, entonces el intérprete evalúa el destino excepto por la última llamada __setitem__()
o __setattr__()
.
Ver también
- PEP 526 - Sintaxis para anotaciones de variable
La propuesta que agregó sintaxis para anotar los tipos de variables (incluidas variables de clase y variables de instancia), en lugar de expresarlas a través de comentarios.
- PEP 484 - Indicadores de tipo
La propuesta que agregó el módulo
typing
para proporcionar una sintaxis estándar para las anotaciones de tipo para ser utilizadas en herramientas de análisis estático e IDEs.
Distinto en la versión 3.8: Now annotated assignments allow the same expressions in the right hand side as regular assignments. Previously, some expressions (like un-parenthesized tuple expressions) caused a syntax error.
7.3. La declaración assert
¶
Las declaraciones de afirmación son una forma conveniente de insertar afirmaciones de depuración en un programa:
assert_stmt ::= "assert"expression
[","expression
]
La forma simple, assert expressionn
, es equivalente a
if __debug__:
if not expression: raise AssertionError
La forma extendida, assert expression1, expression2
, es equivalente a
if __debug__:
if not expression1: raise AssertionError(expression2)
Estas equivalencias asumen que __debug__
y AssertionError
se refieren a las variables integradas con esos nombres. En la implementación actual, la variable incorporada __debug__
es True
en circunstancias normales, False
cuando se solicita la optimización (opción de línea de comando -O
). El generador de código actual no emite código para una declaración de aserción cuando se solicita la optimización en tiempo de compilación. Tenga en cuenta que no es necesario incluir el código fuente de la expresión que falló en el mensaje de error; se mostrará como parte del seguimiento de la pila.
Asignaciones a __debug__
son ilegales. El valor para la variable se determina cuando arranca el intérprete.
7.4. La declaración pass
¶
pass_stmt ::= "pass"
pass
es una operación nula — cuando se ejecuta, no sucede nada. Es útil como marcador de posición cuando se requiere una declaración sintácticamente, pero no es necesario ejecutar código, por ejemplo:
def f(arg): pass # a function that does nothing (yet)
class C: pass # a class with no methods (yet)
7.5. La declaración del
¶
del_stmt ::= "del" target_list
La eliminación se define de forma recursiva de manera muy similar a la forma en que se define la asignación. En lugar de explicarlo con todos los detalles, aquí hay algunas sugerencias.
La eliminación de una lista de objetivos elimina cada objetivo de forma recursiva, de izquierda a derecha.
La eliminación de un nombre elimina la vinculación de ese nombre del espacio de nombres local o global, dependiendo de si el nombre aparece en una declaración global
en el mismo bloque de código. Si el nombre no está vinculado, se lanzará una excepción NameError
.
La supresión de referencias de atributo, suscripciones y rebanadas se pasa al objeto primario involucrado; la eliminación de una rebanada es en general equivalente a la asignación de una rebanada vacía del tipo correcto (pero incluso esto está determinado por el objeto rebanado).
Distinto en la versión 3.2: Anteriormente era ilegal eliminar un nombre del espacio de nombres local si aparece como una variable libre en un bloque anidado.
7.6. La declaración return
¶
return_stmt ::= "return" [expression_list
]
El return
sólo puede ocurrir sintácticamente anidado en una definición de función, no dentro de una definición de clase anidada.
Si una lista de expresiones es presente, ésta es evaluada, sino es substituida por None
.
return
deja la llamada a la función actual con la lista de expresiones (o None
) como valor de retorno.
Cuando return
pasa el control de una sentencia try
con una cláusula finally
, esa cláusula finally
se ejecuta antes de dejar realmente la función.
En una función generadora, la declaración return
indica que el generador ha acabado y hará que StopIteration
se lance. El valor retornado (si lo hay) se utiliza como argumento para construir StopIteration
y se convierte en el atributo StopIteration.value
.
En una función de generador asíncrono, una declaración return
vacía indica que el generador asíncrono ha acabado y va a lanzar un StopAsyncIteration
. Una declaración return
no vacía es un error de sintaxis en una función generadora asíncrona.
7.7. La declaración yield
¶
yield_stmt ::= yield_expression
La declaración yield
es semánticamente equivalente a yield expression. Una declaración de producción se puede utilizar para omitir los paréntesis que de otro modo serían necesarios en la declaración de expresión de producción equivalente. Por ejemplo, las declaraciones de producción
yield <expr>
yield from <expr>
son equivalentes a las funciones que producen declaraciones
(yield <expr>)
(yield from <expr>)
Expresiones y declaraciones productoras se usan únicamente para definir una función generator, y son utilizadas únicamente en el cuerpo de una función generadora. Usar producción en una definición de función es suficiente para hacer que esa definición cree una función generadora en lugar de una función normal.
Para todos los detalles de la semántica de yield
, referirse a la sección Expresiones yield.
7.8. La declaración raise
¶
raise_stmt ::= "raise" [expression
["from"expression
]]
If no expressions are present, raise
re-raises the
exception that is currently being handled, which is also known as the active exception.
If there isn’t currently an active exception, a RuntimeError
exception is raised
indicating that this is an error.
De lo contrario, raise
evalúa la primera expresión como el objeto de excepción. Debe ser una subclase o una instancia de BaseException
. Si es una clase, la instancia de excepción se obtendrá cuando sea necesario creando una instancia de la clase sin argumentos.
El type de la excepción es la instancia de la clase excepción, el value es la propia instancia.
A traceback object is normally created automatically when an exception is raised
and attached to it as the __traceback__
attribute, which is writable.
You can create an exception and set your own traceback in one step using the
with_traceback()
exception method (which returns the
same exception instance, with its traceback set to its argument), like so:
raise Exception("foo occurred").with_traceback(tracebackobj)
La cláusula from
se utiliza para el encadenamiento de excepciones: si se proporciona, el segundo expression debe ser otra clase o instancia de excepción. Si la segunda expresión es una instancia de excepción, se adjuntará a la excepción generada como el atributo __cause__
(que se puede escribir). Si la expresión es una clase de excepción, se creará una instancia de la clase y la instancia de excepción resultante se adjuntará a la excepción generada como el atributo __cause__
. Si no se maneja la excepción generada, se imprimirán ambas excepciones:
>>> try:
... print(1 / 0)
... except Exception as exc:
... raise RuntimeError("Something bad happened") from exc
...
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
ZeroDivisionError: division by zero
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "<stdin>", line 4, in <module>
RuntimeError: Something bad happened
A similar mechanism works implicitly if a new exception is raised when
an exception is already being handled. An exception may be handled
when an except
or finally
clause, or a
with
statement, is used. The previous exception is then
attached as the new exception’s __context__
attribute:
>>> try:
... print(1 / 0)
... except:
... raise RuntimeError("Something bad happened")
...
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
ZeroDivisionError: division by zero
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "<stdin>", line 4, in <module>
RuntimeError: Something bad happened
El encadenamiento de excepciones se puede suprimir explícitamente especificando None
en la cláusula from
:
>>> try:
... print(1 / 0)
... except:
... raise RuntimeError("Something bad happened") from None
...
Traceback (most recent call last):
File "<stdin>", line 4, in <module>
RuntimeError: Something bad happened
Se puede encontrar información adicional sobre excepciones en la sección Excepciones, e información sobre manejo de excepciones en la sección La sentencia try.
Distinto en la versión 3.3: None
ahora es permitido como Y
en raise X from Y
.
Nuevo en la versión 3.3: El atributo __suppress_context__
para suprimir la visualización automática del contexto de excepción.
7.9. La declaración break
¶
break_stmt ::= "break"
break
solo puede ocurrir sintácticamente anidado en un bucle for
o while
, pero no anidado en una función o definición de clase dentro de ese bucle.
Termina el bucle adjunto más cercano, omitiendo la cláusula else
opcional si el bucle tiene una.
Si un bucle for
es terminado por break
, el objetivo de control de bucle mantiene su valor actual.
Cuando break
pasa el control de una sentencia try
con una cláusula finally
, esa cláusula finally
se ejecuta antes de dejar realmente el bucle.
7.10. La declaración continue
¶
continue_stmt ::= "continue"
continue
sólo puede ocurrir sintácticamente anidado en el ciclo for
o while
, pero no anidado en una función o definición de clase dentro de ese ciclo. Continúa con la siguiente iteración del bucle envolvente más cercano.
Cuando continue
pasa el control de una sentencia try
con una cláusula finally
, esa cláusula finally
se ejecuta antes de empezar realmente el siguiente ciclo del bucle.
7.11. La declaración import
¶
import_stmt ::= "import"module
["as"identifier
] (","module
["as"identifier
])* | "from"relative_module
"import"identifier
["as"identifier
] (","identifier
["as"identifier
])* | "from"relative_module
"import" "("identifier
["as"identifier
] (","identifier
["as"identifier
])* [","] ")" | "from"relative_module
"import" "*" module ::= (identifier
".")*identifier
relative_module ::= "."*module
| "."+
La declaración básica de importación (sin la cláusula from
) es ejecutada en 2 pasos:
encontrar un módulo, cargarlo e inicializarlo en caso de ser necesario
define un nombre o nombres en el espacio de nombres local para el alcance donde ocurre la instrucción
import
.
Cuando la declaración contiene varias cláusulas (separadas por comas), los dos pasos se llevan a cabo por separado para cada cláusula, como si las cláusulas se hubieran separado en declaraciones de importación individuales.
The details of the first step, finding and loading modules, are described in greater detail in the section on the import system, which also describes the various types of packages and modules that can be imported, as well as all the hooks that can be used to customize the import system. Note that failures in this step may indicate either that the module could not be located, or that an error occurred while initializing the module, which includes execution of the module’s code.
Si el módulo solicitado se recupera correctamente, estará disponible en el espacio de nombres local de una de estas tres formas:
Si el nombre del módulo va seguido de
as`
, entonces el nombre siguienteas
está vinculado directamente al módulo importado.Si no se especifica ningún otro nombre y el módulo que se está importando es un módulo de nivel superior, el nombre del módulo se enlaza en el espacio de nombres local como una referencia al módulo importado
Si el módulo que se está importando no es un módulo de nivel superior, entonces el nombre del paquete de nivel superior que contiene el módulo se enlaza en el espacio de nombres local como una referencia al paquete de nivel superior. Se debe acceder al módulo importado utilizando su nombre calificado completo en lugar de directamente
La forma from
usa un complejo un poco más complicado:
encuentra el módulo especificado en la cláusula
from
, cargando e inicializándolo si es necesario;para cada uno de los identificadores especificados en la cláusula
import
:compruebe si el módulo importado tiene un atributo con ese nombre
de lo contrario, intente importar un submódulo con ese nombre y luego verifique el módulo importado nuevamente para ese atributo
si el atributo no se encuentra,
ImportError
es lanzada.de lo contrario, una referencia a ese valor se almacena en el espacio de nombres local, usando el nombre en la cláusula
as
si ésta está presente, de lo contrario usando el nombre del atributo
Ejemplos:
import foo # foo imported and bound locally
import foo.bar.baz # foo, foo.bar, and foo.bar.baz imported, foo bound locally
import foo.bar.baz as fbb # foo, foo.bar, and foo.bar.baz imported, foo.bar.baz bound as fbb
from foo.bar import baz # foo, foo.bar, and foo.bar.baz imported, foo.bar.baz bound as baz
from foo import attr # foo imported and foo.attr bound as attr
Si la lista de identificadores se reemplaza por una estrella (’*’
), todos los nombres públicos definidos en el módulo se enlazan en el espacio de nombres local para el ámbito donde ocurre la declaración import
.
Los nombres públicos definidos por un módulo se determinan al verificar el espacio de nombres del módulo en busca de una variable llamada __all__
; si se define, debe ser una secuencia de cadenas que son nombres definidos o importados por ese módulo. Los nombres dados en __all__
se consideran públicos y se requiere que existan. Si __all__
no está definido, el conjunto de nombres públicos incluye todos los nombres que se encuentran en el espacio de nombres del módulo que no comienzan con un carácter de subrayado (’_’
). __all__
debe contener la API pública completa. Su objetivo es evitar la exportación accidental de elementos que no forman parte de la API (como los módulos de biblioteca que se importaron y utilizaron dentro del módulo).
La forma de importación comodín — from module import *
— sólo se permite a nivel módulo. Intentar usarlo en una definición de clase o función lanza una SyntaxError
.
Al especificar qué módulo importar, no es necesario especificar el nombre absoluto del módulo. Cuando un módulo o paquete está contenido dentro de otro paquete, es posible realizar una importación relativa dentro del mismo paquete superior sin tener que mencionar el nombre del paquete. Al usar puntos iniciales en el módulo o paquete especificado después de from
, puede especificar qué tan alto recorrer la jerarquía actual del paquete sin especificar nombres exactos. Un punto inicial significa el paquete actual donde existe el módulo que realiza la importación. Dos puntos significan un nivel de paquete. Tres puntos son dos niveles, etc. Entonces, si ejecuta from . import mod
de un módulo en el paquete pkg
terminará importando``pkg.mod``. Si ejecuta from ..subpkg2 import mod
desde dentro de pkg.subpkg1
, importará pkg.subpkg2.mod
. La especificación para las importaciones relativas está contenida en la sección Paquete Importaciones relativas.
importlib.import_module()
se proporciona para soportar aplicaciones que determinan dinámicamente los módulos a cargar.
Lanza un auditing event import
con argumentos module
, filename
, sys.path
, sys.meta_path
, sys.path_hooks
.
7.11.1. Declaraciones Futuras¶
Una future statement es una directiva para el compilador para indicar que un módulo en particular debe compilarse usando la sintaxis o semántica que estará disponible en una versión futura específica de Python donde la característica se convierte en estándar.
La declaración futura está destinada a facilitar la migración a futuras versiones de Python que introducen cambios incompatibles en el lenguaje. Permite el uso de las nuevas funciones por módulo antes del lanzamiento en el que la función se convierte en estándar.
future_stmt ::= "from" "__future__" "import"feature
["as"identifier
] (","feature
["as"identifier
])* | "from" "__future__" "import" "("feature
["as"identifier
] (","feature
["as"identifier
])* [","] ")" feature ::=identifier
Una declaración futura debe aparecer cerca de la parte superior del módulo. Las únicas líneas que pueden aparecer antes de una declaración futura son:
el docstring del módulo (si hay),
comentarios,
lineas en blanco, y
otras declaraciones futuras.
La única característica en Python 3.7 que requiere el uso la declaración futuro es annotations
.
108/5000
Python 3 aún reconoce todas las características históricas habilitadas por la declaración futura. La lista incluye absolute_import
, division
, generators
, generator_stop
, unicode_literals
, print_function
, nested_scopes
y with_statement
. Todos son redundantes porque siempre están habilitados y solo se conservan para compatibilidad con versiones anteriores.
Una declaración futura se reconoce y se trata especialmente en el momento de la compilación: los cambios en la semántica de las construcciones centrales a menudo se implementan generando código diferente. Incluso puede darse el caso de que una nueva característica introduzca una nueva sintaxis incompatible (como una nueva palabra reservada), en cuyo caso el compilador puede necesitar analizar el módulo de manera diferente. Tales decisiones no pueden postergarse hasta el tiempo de ejecución.
Para cualquier versión dada, el compilador sabe qué nombres de características se han definido y lanza un error en tiempo de compilación si una declaración futura contiene una característica que no conoce.
La semántica del tiempo de ejecución directo es la misma que para cualquier declaración de importación: hay un módulo estándar __future__
, que se describe más adelante, y se importará de la forma habitual en el momento en que se ejecute la declaración futura.
La interesante semántica del tiempo de ejecución depende de la característica específica habilitada por la declaración futura.
Notar que no hay nada especial a cerca de la declaración:
import __future__ [as name]
Esa no es una declaración futura; es una declaración de importación ordinaria sin restricciones especiales de semántica o sintaxis.
El código compilado por llamadas a las funciones integradas exec()
y compile()
que ocurren en un módulo M
que contiene una declaración futura usará, por defecto, la nueva sintaxis o semántica asociada con la declaración futura. Esto se puede controlar mediante argumentos opcionales para compile()
— consulte la documentación de esa función para obtener más detalles.
Una declaración futura escrita en una prompt interactiva del intérprete entrará en vigencia durante el resto de la sesión de dicho intérprete. Si un intérprete se inicia con la opción -i
, se le pasa un nombre de script para ejecutar, y el script incluye una declaración futura, ésta estará en efecto en la sesión interactiva iniciada después de que se ejecute el script.
Ver también
- PEP 236 - Vuelta al __future__
La propuesta original para el mecanismo __future__.
7.12. La declaración global
¶
global_stmt ::= "global"identifier
(","identifier
)*
La declaración global
es una declaración que se aplica a todo el bloque de código actual. Significa que los identificadores enumerados deben interpretarse como globales. Sería imposible asignar a una variable global sin global
, aunque las variables libres pueden referirse a globales sin ser declaradas globales.
Los nombres enumerados en una declaración global
no deben usarse en el mismo bloque de código que precede textualmente a la declaración global
.
Los nombres enumerados en una declaración global
no deben definirse como parámetros formales, o como destinos en declaraciones with
o cláusulas except
, o en una lista de destino for
, definición de class
, definición de función, declaración import
o anotación de variable.
Detalles de implementación de CPython: La implementación actual no hace cumplir algunas de estas restricciones, pero los programas no deben abusar de esta libertad, ya que las implementaciones futuras pueden imponerlas o cambiar silenciosamente el significado del programa.
** Nota del programador: ** global
es una directiva para el analizador. Se aplica solo al código analizado al mismo tiempo que la declaración global
. En particular, una declaración global
contenida en una cadena u objeto de código suministrado a la función incorporada exec()
no afecta el bloque de código que contiene la llamada a la función, y el código contenido en dicha función una cadena no se ve afectada por la declaración keyword:!global en el código que contiene la llamada a la función. Lo mismo se aplica a las funciones eval()
y compile()
.
7.13. La declaración nonlocal
¶
nonlocal_stmt ::= "nonlocal"identifier
(","identifier
)*
La declaración nonlocal
hace que los identificadores enumerados se refieran a variables vinculadas previamente en el ámbito circundante más cercano excluyendo globales. Esto es importante porque el comportamiento predeterminado para el enlace es buscar primero en el espacio de nombres local. La declaración permite que el código encapsulado vuelva a vincular variables fuera del ámbito local además del ámbito global (módulo).
Los nombres enumerados en una instrucción nonlocal
, a diferencia de los enumerados en una instrucción global
, deben hacer referencia a enlaces preexistentes en un ámbito adjunto (no se puede determinar el ámbito en el que se debe crear un nuevo enlace inequívocamente).
Los nombres enumerados en la declaración nonlocal
no deben colisionar con las enlaces preexistentes en el ámbito local.