Espacios de nombres y ámbitos en Python3

Espacio de nombres

Primero veamos un párrafo de la documentación oficial:

A namespace is a mapping from names to objects.Most namespaces are currently implemented as Python dictionaries.

Un espacio de nombres (Namespace) es una asignación de nombres a objetos; la mayoría de los espacios de nombres se implementan mediante diccionarios de Python.

Los espacios de nombres proporcionan una manera de evitar conflictos de nombres en un proyecto. Cada espacio de nombres es independiente y no tiene relación con los demás, por lo que en un espacio de nombres no puede haber nombres repetidos, pero diferentes espacios de nombres pueden tener los mismos nombres sin ningún efecto.

Pongamos un ejemplo de un sistema informático: una carpeta (directorio) puede contener varias carpetas; cada carpeta no puede tener archivos con el mismo nombre, pero archivos en diferentes carpetas sí pueden tener el mismo nombre.

Generalmente hay tres tipos de espacios de nombres:

  • Nombres integrados (built-in names), nombres integrados en el lenguaje Python, como los nombres de funciones abs, char y nombres de excepción BaseException, Exception, etc.
  • Nombres globales (global names), nombres definidos en un módulo, que registran las variables del módulo, incluyendo funciones, clases, otros módulos importados, y variables y constantes a nivel de módulo.
  • Nombres locales (local names), nombres definidos en una función, que registran las variables de la función, incluyendo los parámetros de la función y las variables definidas localmente. (También los definidos en una clase).

Orden de búsqueda en los espacios de nombres:

Supongamos que queremos usar la variable ejemplo; entonces el orden de búsqueda de Python es:Espacio de nombres local -> Espacio de nombres global -> Espacio de nombres integrado。

Si no se encuentra la variable ejemplo, abandonará la búsqueda y lanzará una excepción NameError:

NameError: name 'ejemplo' is not defined.

Ciclo de vida de los espacios de nombres:

El ciclo de vida de un espacio de nombres depende del ámbito del objeto; si el objeto termina de ejecutarse, el ciclo de vida de ese espacio de nombres finaliza.

Por lo tanto, no podemos acceder a los objetos de un espacio de nombres interno desde un espacio de nombres externo.

Ejemplo

# var1 es un nombre global
var1 = 5
def some_func():
 
    # var2 es un nombre local
    var2 = 6
    def some_inner_func():
 
        # var3 es un nombre local anidado
        var3 = 7

Como se muestra en la figura siguiente, el mismo nombre de objeto puede existir en múltiples espacios de nombres.


Ámbito

A scope is a textual region of a Python program where a namespace is directly accessible. "Directly accessible" here means that an unqualified reference to a name attempts to find the name in the namespace.

Un ámbito es la región textual de un programa Python en la que se puede acceder directamente a un espacio de nombres.

En un programa Python, al acceder directamente a una variable, se recorren todos los ámbitos de adentro hacia afuera hasta encontrarla; de lo contrario, se produce un error de variable no definida.

En Python, no se puede acceder a las variables del programa desde cualquier posición; el permiso de acceso depende de dónde se asigne la variable.

El ámbito de una variable determina en qué parte del programa se puede acceder a un nombre de variable específico.

Python tiene un total de 4 tipos de ámbito, que son:

Hay cuatro ámbitos:

  • L(Local): el más interno, contiene variables locales, por ejemplo, dentro de una función/método.
  • E(Enclosing): contiene variables no locales (non-local) ni globales (non-global). Por ejemplo, en dos funciones anidadas, si una función (o clase) A contiene a su vez una función B, entonces para los nombres dentro de B, el ámbito dentro de A es nonlocal.
  • G(Global): la capa más externa del script actual, por ejemplo, las variables globales del módulo actual.
  • B(Built-in): contiene variables/palabras clave integradas, etc. Es lo último que se busca.

Regla LEGB (Local, Enclosing, Global, Built-in): el orden de búsqueda de variables en Python es:L –> E –> G –> B。

  1. Local: el ámbito local de la función actual.
  2. Enclosing: contiene el ámbito de la función externa que envuelve a la función actual (si hay funciones anidadas).
  3. Global: el ámbito global del módulo actual.
  4. Built-in: el ámbito integrado de Python.

Si no se encuentra en el ámbito local, se buscará en los ámbitos locales externos (por ejemplo, en un cierre), luego en el global y después en el integrado.

g_count = 0  # 全局作用域
def outer():
    o_count = 1  # 闭包函数外的函数中
    def inner():
        i_count = 2  # 局部作用域

El ámbito integrado se implementa mediante un módulo estándar llamado builtin, pero este nombre de variable en sí no está dentro del ámbito integrado, por lo que es necesario importar este archivo para poder usarlo. En Python 3.0, se puede usar el siguiente código para ver qué variables están predefinidas:

>>> import builtins
>>> dir(builtins)

En Python solo los módulos, las clases y las funciones (def, lambda) introducen un nuevo ámbito; otros bloques de código (como if/elif/else, try/except, for/while, etc.) no introducen un nuevo ámbito. Es decir, las variables definidas dentro de estas sentencias también son accesibles desde fuera, como en el siguiente código:

>>> if True:
...  msg = 'I am from Ejemplo'
... 
>>> msg
'I am from Ejemplo'
>>> 

En el ejemplo, la variable msg está definida dentro del bloque de la sentencia if, pero aún así se puede acceder a ella desde fuera.

Si msg se define dentro de una función, entonces es una variable local y no se puede acceder desde fuera:

>>> def test():
...     msg_inner = 'I am from Ejemplo'
... 
>>> msg_inner
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'msg_inner' is not defined
>>> 

Según el mensaje de error, indica que msg_inner no está definido y no se puede usar, porque es una variable local y solo puede usarse dentro de la función.

Variables globales y locales

Las variables definidas dentro de una función tienen un ámbito local; las definidas fuera de una función tienen un ámbito global.

Las variables locales solo se pueden acceder dentro de la función donde se declaran, mientras que las variables globales se pueden acceder en todo el programa.

Las variables declaradas dentro de una función solo son válidas en el ámbito de esa función; al llamar a la función, estas variables internas se añaden al ámbito interno de la función y no afectan a variables del mismo nombre fuera de la función, como en el siguiente ejemplo:

Ejemplo (Python 3.0+)

#!/usr/bin/python3 total = 0 # Esta es una variable global # Documentación de la función def sum( arg1, arg2 ): # Devuelve la suma de 2 parámetros. total = arg1 + arg2 # total aquí es una variable local. print ("Dentro de la función es una variable local:", total) return total # Llamar a la función sum sum( 10, 20 ) print ("Fuera de la función es una variable global:", total)

El resultado del ejemplo anterior es:

函数内是局部变量 :  30
函数外是全局变量 :  0

1. Variable global: variable definida fuera de la función, accesible en todo el archivo. Las variables definidas fuera de una función son visibles para todas las funciones, a menos que dentro de la función se defina una variable local del mismo nombre.

Ejemplo

x = 10  # Variable global

def my_function():
    print(x)  # Se puede acceder a la variable global x

my_function()  # Imprime 10

2. Variable local: variable definida dentro de una función, solo válida dentro de la función; fuera de la función no se puede acceder. Las variables locales tienen prioridad sobre las globales, por lo que si una variable local y una global tienen el mismo nombre, la función usará la variable local.

Ejemplo

def my_function():
    x = 5  # Variable local
    print(x)  # Acceder a la variable local x

my_function()  # Imprime 5
print(x)  # Error: NameError: name 'x' is not defined

Las palabras clave global y nonlocal

Cuando un ámbito interno quiere modificar una variable de un ámbito externo, se necesitan las palabras clave global y nonlocal.

El siguiente ejemplo modifica la variable global num:

Ejemplo (Python 3.0+)

#!/usr/bin/python3 num = 1 def fun1(): global num # Se necesita usar la palabra clave global para declarar print(num) num = 123 print(num) fun1() print(num)

El resultado del ejemplo anterior es:

1
123
123

Si se quiere modificar una variable en un ámbito anidado (ámbito enclosing, el ámbito externo no global), se necesita la palabra clave nonlocal, como en el siguiente ejemplo:

Ejemplo (Python 3.0+)

#!/usr/bin/python3 def outer(): num = 10 def inner(): nonlocal num # Declaración con la palabra clave nonlocal num = 100 print(num) inner() print(num) outer()

El resultado del ejemplo anterior es:

100
100

Además, hay un caso especial: supongamos que se ejecuta el siguiente código:

Ejemplo (Python 3.0+)

#!/usr/bin/python3 a = 10 def test(): a = a + 1 print(a) test()

Al ejecutar el programa anterior, el mensaje de error es el siguiente:

Traceback (most recent call last):
  File "test.py", line 7, in <module>
    test()
  File "test.py", line 5, in test
    a = a + 1
UnboundLocalError: local variable 'a' referenced before assignment

El mensaje de error es un error de referencia en el ámbito local, porque en la función test se usa a como local, no está definida y no se puede modificar.

Modificar a como variable global:

Ejemplo

#!/usr/bin/python3 a = 10 def test(): global a a = a + 1 print(a) test()

El resultado de la ejecución es:

11

También se puede pasar mediante parámetros de función:

Ejemplo (Python 3.0+)

#!/usr/bin/python3 a = 10 def test(a): a = a + 1 print(a) test(a)

El resultado de la ejecución es:

11

Resumen

  • Variable globalDefinida fuera de la función, se puede acceder en todo el archivo.
  • Variable localDefinida dentro de la función, solo se puede acceder dentro de la función.
  • UsoglobalSe pueden modificar variables globales en una función.
  • UsononlocalSe pueden modificar variables de la función externa en una función anidada.
Otras extensiones