28- 馃攳 Scope en Python: Gu铆a B谩sica y Ejemplos

Acorde贸n de los 脥ndices




Python Scope

馃寪 Python Scope: La Visibilidad de las Variables

El **scope** en Python determina la visibilidad de los nombres (variables, funciones, clases, etc.) dentro de un programa. Define las regiones del c贸digo desde donde se puede acceder a un nombre en particular. Python sigue un conjunto de reglas para determinar el scope de una variable.

La comprensi贸n del scope es fundamental para:

  • Evitar conflictos de nombres: Permite usar el mismo nombre de variable en diferentes partes del programa sin que interfieran entre s铆.
  • Organizar el c贸digo: Ayuda a encapsular variables dentro de ciertas secciones del c贸digo, haci茅ndolo m谩s modular y legible.
  • Gestionar la vida 煤til de las variables: Las variables tienen un ciclo de vida limitado por su scope.

Reglas del Scope en Python: El Acr贸nimo LEGB

Python utiliza la regla **LEGB** para determinar el scope de un nombre cuando se hace referencia a 茅l:

  1. Local (L): El scope de los nombres definidos dentro de una funci贸n. Estos nombres solo son accesibles desde el interior de la funci贸n donde se definieron.
  2. Enclosing function locals (E): El scope de los nombres en las funciones envolventes (para funciones anidadas). Si un nombre no se encuentra en el scope local, Python busca en los scopes locales de todas las funciones envolventes, de adentro hacia afuera.
  3. Global (G): El scope de los nombres definidos en el nivel superior del m贸dulo o archivo del programa. Las variables globales son accesibles desde cualquier parte del programa.
  4. Built-in (B): El scope de los nombres predefinidos en el lenguaje Python (funciones como print(), len(), excepciones como TypeError, etc.). Estos nombres siempre est谩n disponibles.

Python busca un nombre en estos scopes en el orden LEGB. El primer lugar donde se encuentra el nombre es el scope que se utiliza.

Ejemplo Ilustrativo:

      
# Scope Global
variable_global = 10

def funcion_externa():
    # Scope de la funci贸n envolvente (Enclosing)
    variable_envolvente = 20

    def funcion_interna():
        # Scope Local
        variable_local = 30
        print(variable_local)      # Accede a la variable local (L)
        print(variable_envolvente) # Accede a la variable de la funci贸n envolvente (E)
        print(variable_global)     # Accede a la variable global (G)
        print(len("Hola"))         # Accede a la funci贸n built-in (B)

    funcion_interna()

funcion_externa()
print(variable_global)         # Accede a la variable global (G)

try:
    print(variable_local)      # Generar谩 un NameError: variable_local no est谩 definida en el scope global
except NameError as e:
    print(f"Error: {e}")

try:
    print(variable_envolvente) # Generar谩 un NameError: variable_envolvente no est谩 definida en el scope global
except NameError as e:
    print(f"Error: {e}")
      
     

En los siguientes temas, exploraremos en detalle los scopes local y global, as铆 como las palabras clave global y nonlocal.

Local Scope

馃搷 Local Scope: Dentro de las Funciones

El **scope local** se refiere al 谩mbito de las variables que se definen dentro del cuerpo de una funci贸n. Estas variables son creadas cuando se llama a la funci贸n y dejan de existir cuando la funci贸n termina su ejecuci贸n. Por lo tanto, solo son accesibles desde el interior de la funci贸n en la que fueron definidas.

Caracter铆sticas del Scope Local:

  • Creaci贸n y Destrucci贸n: Las variables locales se crean al invocar la funci贸n y se destruyen al finalizar la funci贸n.
  • Accesibilidad Limitada: Solo el c贸digo dentro de la funci贸n puede acceder directamente a sus variables locales. No se puede acceder a ellas desde fuera de la funci贸n.
  • Nombres Independientes: Se pueden tener variables locales con el mismo nombre en diferentes funciones, ya que cada una existe en su propio scope local y son independientes entre s铆.

Ejemplo Ilustrativo:

      
def mi_funcion():
    variable_local = "Soy local a mi_funcion"
    print(variable_local)

mi_funcion() # Output: Soy local a mi_funcion

try:
    print(variable_local) # Generar谩 un NameError porque variable_local no est谩 definida en el scope global
except NameError as e:
    print(f"Error: {e}")

def otra_funcion():
    otra_variable_local = 100
    print(otra_variable_local)

otra_funcion() # Output: 100

try:
    print(otra_variable_local) # Generar谩 un NameError porque otra_variable_local no est谩 definida en el scope global
except NameError as e:
    print(f"Error: {e}")
      
     

En este ejemplo, variable_local solo existe dentro de mi_funcion(), y otra_variable_local solo existe dentro de otra_funcion(). Intentar acceder a ellas fuera de sus respectivas funciones resulta en un NameError.

Variables Locales y Argumentos de Funci贸n:

Los par谩metros que se definen en la firma de una funci贸n tambi茅n se consideran variables locales dentro del cuerpo de esa funci贸n.

      
def saludar(nombre):
    mensaje = f"Hola, {nombre}!"
    print(mensaje)

saludar("Juan") # Output: Hola, Juan!

try:
    print(nombre)  # Generar谩 un NameError
except NameError as e:
    print(f"Error: {e}")

try:
    print(mensaje) # Generar谩 un NameError
except NameError as e:
    print(f"Error: {e}")
      
     

Aqu铆, tanto el par谩metro nombre como la variable mensaje son locales a la funci贸n saludar().

En el siguiente tema, exploraremos el **scope global** en Python.

Global Scope

馃實 Global Scope: En la Cima del Programa

El **scope global** se refiere al 谩mbito de las variables que se definen fuera de cualquier funci贸n o bloque de c贸digo. Estas variables se crean cuando se inicia el programa y persisten hasta que el programa finaliza. En general, son accesibles desde cualquier parte del c贸digo, tanto dentro como fuera de las funciones.

Caracter铆sticas del Scope Global:

  • Definici贸n en el Nivel Superior: Las variables globales se definen en el nivel m谩s alto del archivo del programa (o m贸dulo).
  • Accesibilidad General: Se puede acceder a las variables globales desde cualquier funci贸n o parte del c贸digo.
  • Persistencia: Las variables globales existen durante toda la ejecuci贸n del programa.

Ejemplo Ilustrativo:

      
mensaje_global = "Soy una variable global"

def mostrar_mensaje():
    print(mensaje_global) # Accede a la variable global

mostrar_mensaje() # Output: Soy una variable global
print(mensaje_global) # Output: Soy una variable global

contador = 0

def incrementar_contador():
    global contador # Necesitamos usar 'global' para modificar la variable global
    contador += 1
    print(f"Contador ahora es: {contador}")

incrementar_contador() # Output: Contador ahora es: 1
incrementar_contador() # Output: Contador ahora es: 2
print(f"Valor global de contador: {contador}") # Output: Valor global de contador: 2
      
     

En este ejemplo, mensaje_global y contador son variables definidas en el scope global. La funci贸n mostrar_mensaje() puede acceder a mensaje_global directamente. Sin embargo, para modificar una variable global dentro de una funci贸n, se necesita utilizar la palabra clave global (como se muestra en incrementar_contador()), de lo contrario, Python tratar铆a contador dentro de la funci贸n como una nueva variable local.

Precauciones con las Variables Globales:

Si bien las variables globales pueden ser convenientes en algunos casos, su uso excesivo puede llevar a un c贸digo m谩s dif铆cil de entender y mantener. Pueden hacer que las funciones sean menos independientes y m谩s propensas a efectos secundarios no deseados. En general, se recomienda limitar el uso de variables globales y preferir pasar datos a las funciones como argumentos y devolver resultados.

La Importancia de la Palabra Clave global:

Como se mencion贸 en el ejemplo, si intentas asignar un valor a una variable dentro de una funci贸n, Python asumir谩 que es una nueva variable local, incluso si existe una variable con el mismo nombre en el scope global. Para modificar una variable global desde dentro de una funci贸n, debes declararla como global al principio de la funci贸n.

En el siguiente tema, hablaremos sobre las convenciones para nombrar variables en relaci贸n con su scope.

Naming Variables

馃彿️ Nombrando Variables: Claridad y Convenci贸n

Elegir buenos nombres para las variables es una parte crucial de la programaci贸n. Los nombres de las variables deben ser lo suficientemente descriptivos para que cualquier persona (incluido t煤 mismo en el futuro) pueda entender f谩cilmente el prop贸sito de la variable. En relaci贸n con el scope, aunque Python permite usar el mismo nombre para variables en diferentes scopes (local y global, por ejemplo), es importante hacerlo con cuidado para evitar confusiones.

Convenciones Generales para Nombres de Variables en Python:

  • Ser Descriptivo: El nombre debe indicar claramente qu茅 almacena la variable. Por ejemplo, nombre_usuario es mejor que n.
  • Usar Snake Case: Para nombres de variables con m煤ltiples palabras, se recomienda usar snake case, donde las palabras se separan por guiones bajos (ej. cantidad_total, indice_actual).
  • Evitar Palabras Reservadas: No uses palabras reservadas de Python (como if, for, while, def, class, etc.) como nombres de variables.
  • Ser Consistente: Mant茅n un estilo de nombrado coherente en todo tu proyecto.
  • Nombres Cortos para Scopes Peque帽os: En scopes locales muy peque帽os (como contadores en un bucle corto), nombres cortos como i o j pueden ser aceptables.

Nombres y Scope: Evitando Confusiones

Aunque es t茅cnicamente posible tener una variable global y una variable local con el mismo nombre, generalmente se desaconseja porque puede hacer que el c贸digo sea m谩s dif铆cil de leer y entender. Cuando Python encuentra un nombre dentro de una funci贸n, primero busca en el scope local. Si encuentra una variable con ese nombre, la utiliza, incluso si hay una variable global con el mismo nombre.

Ejemplo de Sombreamiento de Variables (Variable Shadowing):

      
variable_compartida = "Soy global"

def mi_funcion():
    variable_compartida = "Soy local" # Esta variable local "sombra" a la global
    print(variable_compartida) # Output: Soy local

mi_funcion()
print(variable_compartida) # Output: Soy global
      
     

En este caso, dentro de mi_funcion(), variable_compartida se refiere a la variable local definida dentro de la funci贸n. La variable global con el mismo nombre queda "sombreada" y no se accede a ella dentro de la funci贸n (a menos que se use la palabra clave global).

Recomendaciones:

  • Usar Nombres Distintos: Siempre que sea posible, utiliza nombres diferentes para las variables en diferentes scopes para evitar el sombreamiento y la confusi贸n.
  • Claridad sobre Intenci贸n: Si necesitas acceder o modificar una variable global dentro de una funci贸n, utiliza expl铆citamente la palabra clave global para que la intenci贸n quede clara.
  • Considerar el Contexto: Elige nombres que tengan sentido dentro del contexto de su scope. Una variable llamada contador podr铆a ser perfectamente aceptable dentro de una funci贸n, pero un nombre m谩s descriptivo podr铆a ser necesario a nivel global.

En los siguientes temas, exploraremos en detalle las palabras clave global y nonlocal, que nos permiten interactuar con variables en scopes diferentes al local.

Global Keyword

馃攽 La Palabra Clave global: Accediendo al 脕mbito Superior

La palabra clave global se utiliza dentro de una funci贸n para indicar que una variable a la que se hace referencia debe ser buscada en el scope global. Esto es especialmente importante cuando se desea modificar el valor de una variable global desde el interior de una funci贸n. Sin la palabra clave global, cualquier asignaci贸n a una variable dentro de una funci贸n crear铆a una nueva variable local con ese nombre, incluso si ya existe una variable global con el mismo nombre (como vimos en el ejemplo de sombreamiento).

Cu谩ndo Usar global:

  • Modificar una Variable Global: Si necesitas cambiar el valor de una variable que fue definida fuera de la funci贸n (en el scope global), debes declararla como global dentro de la funci贸n antes de realizar la asignaci贸n.
  • Acceder a una Variable Global (Opcional pero Recomendado para Claridad): Aunque puedes acceder al valor de una variable global dentro de una funci贸n sin usar global (Python buscar谩 en el scope global si no la encuentra localmente), usar global al principio de la funci贸n puede hacer que tu intenci贸n sea m谩s expl铆cita y el c贸digo m谩s legible.

Ejemplo de Modificaci贸n de una Variable Global:

      
contador_global = 0

def incrementar():
    global contador_global
    contador_global += 1

incrementar()
incrementar()
print(f"El valor de contador_global es: {contador_global}") # Output: El valor de contador_global es: 2
      
     

En este ejemplo, al declarar contador_global como global dentro de la funci贸n incrementar(), las operaciones contador_global += 1 modifican directamente la variable contador_global definida en el scope global.

Creaci贸n de una Variable Global Dentro de una Funci贸n (Generalmente Desaconsejado):

Tambi茅n es posible crear una variable global dentro de una funci贸n utilizando la palabra clave global. Si el nombre de la variable no existe en el scope global al momento de la declaraci贸n global dentro de la funci贸n, se crear谩 una nueva variable global.

      
def crear_variable_global():
    global nueva_variable_global
    nueva_variable_global = "Soy una variable global creada dentro de una funci贸n"

crear_variable_global()
print(nueva_variable_global) # Output: Soy una variable global creada dentro de una funci贸n
      
     

Si bien esto es posible, generalmente se considera una pr谩ctica menos clara y puede dificultar el seguimiento de d贸nde se definen las variables globales. Es preferible definir las variables globales en el nivel superior del m贸dulo.

Precauciones al Usar global:

El uso excesivo de la palabra clave global puede hacer que el c贸digo sea m谩s dif铆cil de entender y mantener, ya que las funciones se vuelven dependientes de variables definidas fuera de su scope. Esto puede reducir la modularidad y aumentar el riesgo de efectos secundarios no deseados. En muchos casos, es mejor pasar datos a las funciones como argumentos y devolver resultados para mantener las funciones m谩s independientes y predecibles.

En el siguiente tema, exploraremos la palabra clave nonlocal, que se utiliza en el contexto de funciones anidadas.

Nonlocal Keyword

馃棟️ La Palabra Clave nonlocal: Accediendo al Scope Envolvente

La palabra clave nonlocal se utiliza dentro de una funci贸n anidada para indicar que una variable a la que se hace referencia no es local a la funci贸n anidada ni global, sino que pertenece al scope de una de las funciones envolventes m谩s cercanas.

Cu谩ndo Usar nonlocal:

  • Modificar Variables de Funciones Envolventes: Cuando una funci贸n anidada necesita modificar una variable que est谩 definida en el scope de su funci贸n padre (o una funci贸n abuela, etc.), pero no en su propio scope local ni en el scope global, se debe declarar esa variable como nonlocal dentro de la funci贸n anidada antes de realizar la asignaci贸n.
  • Acceder a Variables de Funciones Envolventes (Impl铆cito): Si solo necesitas leer el valor de una variable de una funci贸n envolvente, Python la encontrar谩 autom谩ticamente gracias a la regla LEGB (en la 'E' de Enclosing). Sin embargo, si planeas modificarla, necesitas nonlocal.

Ejemplo Ilustrativo: Contador en Funci贸n Anidada

      
def funcion_externa():
    contador = 0

    def funcion_interna():
        nonlocal contador
        contador += 1
        print(f"Contador interno: {contador}")

    funcion_interna() # Output: Contador interno: 1
    funcion_interna() # Output: Contador interno: 2
    print(f"Contador externo: {contador}") # Output: Contador externo: 2

funcion_externa()
      
     

En este ejemplo:

  • La variable contador se define en el scope de funcion_externa().
  • Dentro de funcion_interna(), la declaraci贸n nonlocal contador permite que las operaciones sobre contador modifiquen la variable en el scope de funcion_externa().
  • Sin nonlocal, contador += 1 dentro de funcion_interna() habr铆a creado una nueva variable local llamada contador que no afectar铆a a la variable en la funci贸n externa.

Diferencia entre global y nonlocal:

  • global se utiliza para acceder o modificar variables en el scope global (el nivel superior del m贸dulo).
  • nonlocal se utiliza para acceder o modificar variables en el scope de una funci贸n envolvente m谩s cercana (no local ni global).

Restricciones de nonlocal:

  • nonlocal solo puede referirse a variables que ya han sido definidas en el scope de una funci贸n envolvente. No se puede usar para crear nuevas variables en el scope envolvente.
  • Si la variable no se encuentra en ning煤n scope envolvente, se generar谩 un error.

Ejemplo de Error si nonlocal no encuentra la variable:

      
def funcion_externa():
    def funcion_interna():
        nonlocal mensaje # 'mensaje' no est谩 definido en el scope de funcion_externa
        mensaje = "Hola desde la interna"
        print(mensaje)

    funcion_interna() # Generar谩 un SyntaxError o un NameError dependiendo de la versi贸n de Python
      
     

La palabra clave nonlocal es una herramienta poderosa para trabajar con funciones anidadas y mantener el estado entre la funci贸n envolvente y la funci贸n interna.




Publicar un comentario

0 Comentarios