¿Cuál es la relación entre el alcance y los espacios de nombres en Python?

12

En muchos recursos encontré que "alcance" y "espacios de nombres" se usan indistintamente, lo que parece un poco confuso ya que significan cosas diferentes.

  • Ámbito define la región del código donde está disponible un nombre.
  • La regla LEGB define la forma en que se buscan los nombres.
  • El espacio de nombres es un lugar donde buscar nombres.

Entonces leí:

  • "los nombres están vinculados a un espacio de nombres de acuerdo con el lugar al que están asignados ..." (que creo que es el trato con los ámbitos en el ámbito léxico)
  • "las funciones agregan una capa de espacio de nombres adicional a sus programas" [ ref. ] (¿no agregan un alcance local adicional?)
  • "todos los nombres asignados dentro de una definición de función se colocan en el ámbito local (el espacio de nombres asociado con la llamada a la función)".
  • "alcance global, es decir, un espacio de nombres en el que viven las variables creadas (asignadas) en el nivel superior del archivo del módulo".

* todas las citas son del aprendizaje de python 5th edition ch17

¿Son los espacios de nombres en Python la forma en que se implementan los ámbitos? ¿Son la misma cosa? ¿Alguien puede iluminarme?

Nikos
fuente
1
¿Podría proporcionar referencias para las citas? Podría encontrar una, pero no la otra.
jonrsharpe
1
Los espacios de nombres son solo un tipo de ámbito. Ver stackoverflow.com/questions/291978/…
Robert Harvey

Respuestas:

16

Un espacio de nombres es un diccionario que asigna nombres (como cadenas) a valores. Cuando haces una tarea, como a = 1, estás mutando un espacio de nombres. Cuando hace una referencia, por ejemplo print(a), Python mira a través de una lista de espacios de nombres para tratar de encontrar uno con el nombre como clave.

Un ámbito define en qué espacios de nombres se buscará y en qué orden. El alcance de cualquier referencia siempre comienza en el espacio de nombres local y se mueve hacia afuera hasta que alcanza el espacio de nombres global del módulo, antes de pasar a builtins(el espacio de nombres que hace referencia a las funciones y constantes predefinidas de Python, como rangey getattr), que es el final de la línea .

Imagine que tiene una función llamada inner, anidada dentro de una función global llamada outery innercontiene una referencia a un nombre. Python primero busca en el innerespacio de nombres. Si el nombre no está allí, Python busca en el outerespacio de nombres. Si eso falla, Python prueba el globalespacio de nombres del módulo , luego el builtinespacio de nombres, y finalmente arroja un NameErrorsi no se encuentra el nombre.

Cuando decimos que xestá en el espacio de nombres de una función, queremos decir que está definido allí, localmente dentro de la función. Cuando decimos que xestá en el alcance de la función, queremos decir que xestá en el espacio de nombres de la función o en cualquiera de los espacios de nombres externos en los que está anidado el espacio de nombres de la función.

Cada vez que define una función, crea un nuevo espacio de nombres y un nuevo ámbito. El espacio de nombres es el nuevo hash local de nombres. El ámbito es la cadena implícita de espacios de nombres que comienza en el nuevo espacio de nombres, luego se abre paso a través de los espacios de nombres externos (ámbitos externos), hasta el espacio de nombres global (el ámbito global) y hasta los espacios integrados.

Los términos se pueden usar casi indistintamente, pero eso no se debe a que significan lo mismo; es porque se superponen mucho en lo que implican.

Carl Smith
fuente
3
"Los términos pueden usarse casi indistintamente, pero eso no es porque signifiquen lo mismo; es porque se superponen mucho en lo que implican".
Nikos
2
Esta respuesta es correcta en espíritu, pero incorrecta en detalle. Las clases en Python no introducen un nuevo espacio de nombres, por lo que los atributos de la clase deben calificarse con el nombre de la clase y por qué los atributos de la instancia deben calificarse con el nombre de la instancia. Los niveles de espacio de nombres en Python de interno a externo son Local, Cerrando, Global e Integrado. Se puede definir una clase en cualquiera de estos niveles, pero los miembros de una clase siempre deben estar calificados.
Rob Smallshire
Tienes razón. Las clases no funcionan como dije que lo hacen. Estaba pensando que crean un alcance léxico como una función, pero no lo hacen. Actualice la respuesta si tiene tiempo, de lo contrario lo haré en algún momento. Gracias.
Carl Smith
1
+1 respuesta brillante, encapsulando tanta sutileza tan económicamente. Esto me pareció muy útil, ¡gracias!
buscador
1
"Un espacio de nombres es un hash de nombres, pares de valores, muy parecido a un diccionario de Python". Estoy bastante seguro de que los espacios de nombres se almacenan como diccionarios de Python. Por ejemplo, puede editar el espacio de nombres global llamando a globals (), que le permite modificar el diccionario directamente para vincular objetos y nombres: por ejemplo globals () [name] = "object". Gran respuesta de lo contrario.
Evan Rosica
4

Hay un excelente artículo sobre espacios de nombres de Python aquí . Para citar la parte relevante para responder a su pregunta sobre la referencia entre ámbitos y espacios de nombres:

Un ámbito se refiere a una región de un programa desde donde se puede acceder a un espacio de nombres sin un prefijo.

Por ejemplo, imagine un programa simple de lanzamiento de dados:

import random  # 'random' is in module namespace

def roll(sides=6):  # 'roll' is in module namespace, 'sides' is in roll's
    return random.randint(1, sides)  # both 'random' and 'sides' are in scope here

# but sides can't be accessed out here 

roll tiene su propio espacio de nombres , pero los nombres en el espacio de nombres del módulo también están dentro del alcance .

jonrsharpe
fuente
@CarlSmith señala que la documentación inicial de Python dice lo mismo: "Un ámbito es una región textual de un programa de Python donde un espacio de nombre es directamente accesible". "Directamente accesible" aquí significa que una referencia no calificada a un nombre intenta encontrar el nombre en el espacio de nombres. "
jonrsharpe
@CarlSmith aparte del alcance adicional no local / envolvente, ¿eso ha cambiado mucho? Creo que estamos diciendo lo mismo: un espacio de nombres contiene los nombres y valores, y el alcance le indica qué espacios de nombres son accesibles.
jonrsharpe
Eliminé mis viejos comentarios.
Carl Smith