💾Scope y Namespaces
1. ¿Qué son el Scope
y los Namespaces
en Python 3?
Scope
y los Namespaces
en Python 3?Antes de hablar sobre clases, es importante que comprendamos los conceptos de Scope
y Namespace
en Python.
Un Namespace
es un mapeo de nombres a objetos. Los Namespaces
se crean en diferentes momentos y tienen diferentes tiempos de vida.
Durante la ejecución de un programa en Python 3 se crean diferentes Namespaces
que pueden ser accesibles desde diferentes scopes
:
El
Namespace
por defecto que se crea cuando el intérprete de Python se inicia es el que contiene los nombres por defecto de Python. EsteNamespace
nunca se borra.
dir(__builtins__)
['ArithmeticError',
'AssertionError',
'AttributeError',
'BaseException',
'BlockingIOError',
'BrokenPipeError',
'BufferError',
'BytesWarning',
'ChildProcessError',
'ConnectionAbortedError',
'ConnectionError',
'ConnectionRefusedError',
'ConnectionResetError',
'DeprecationWarning',
'EOFError',
'Ellipsis',
...
El
Namespace
global para un módulo se crea cuando se lee la definición del módulo y, normalmente, dura hasta que el intérprete se cierra.
var_modulo = 10
globals()
...
'tuple',
'type',
'vars',
'zip'],
'_i3': 'var_modulo = 10',
'var_modulo': 10,
'_i4': 'globals()'}
El
Namespace
local para una función o cualquier otra estructura de Python se crea cuando se llama a la función, y se borra cuando la función termina. Las invocaciones recursivas tienen cada una su propioNamespace
.
def func():
var_local_func = 5
var_local_func = 10
print(locals())
func()
{'var_local_func': 10}
2. scope
en Python 3
scope
en Python 3El scope
es una región de un programa en Python donde un Namespace
es directamente accesible.
En Python existen diferentes scopes
desde los que se puede acceder a los Namespaces
con algunas particularidades que debemos tener en cuenta:
El
scope
local (o de función) es el bloque de código o cuerpo de cualquier función o expresión en Python. Contiene los nombres que se definen dentro de la función. Estos nombres sólo serán visibles desde el código de la función. Se crea en la llamada a la función, no en la definición de la misma, por lo que habrá tantosscopes
locales diferentes como llamadas a la función.
def func():
var_local_func = 10
print(var_local_func)
func()
10
La variable var_local_func
definida en el Namespace local de la función no es accedida desde un scope global.
var_local_func
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
Cell In[11], line 1
----> 1 var_local_func
NameError: name 'var_local_func' is not defined
El
scope
no local es un ámbito especial que sólo existe para las funciones anidadas. En estos casos elscope
local es el cuerpo de la función anidada y elscope
no local es el ámbito de la función externa. Los nombres delscope
no local son visibles desde el código de las funciones internas y externas.
def func():
var_nonlocal_func = 10
def func2():
var_local_func2 = 2
def func():
var_nonlocal_func = 10
print("Namespace func", locals())
def func2():
var_local_func2 = 5
print("Namespace func2", locals())
func2()
func()
Namespace func {'var_nonlocal_func': 10}
Namespace func2 {'var_local_func2': 5}
La variable var_no_local_func
es visible desde el código de func2
pero la variable var_local_func2
no es visible desde el código de func
def func():
var_nonlocal_func = 10
def func2():
var_local_func2 = 5
print(var_nonlocal_func)
func2()
func()
10
def func():
var_nonlocal_func = 10
print(var_local_func2)
def func2():
var_local_func2 = 5
func2()
func()
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
Cell In[26], line 1
----> 1 func()
Cell In[25], line 3, in func()
1 def func():
2 var_nonlocal_func = 10
----> 3 print(var_local_func)
4 def func2():
5 var_local_func = 5
NameError: name 'var_local_func' is not defined
El
scope
global (o de módulo) es el ámbito superior de un programa, script o módulo de Python. Este ámbito de Python contiene todos los nombres que se definen en el nivel superior de un programa o módulo. Los nombres en este ámbito de Python son visibles desde cualquier parte de tu código.
var_global = 15
print(var_global)
15
def func_global():
def func_local():
print(var_global)
func_local()
func_global()
15
La variable var_global
es accesible desde el código de func
y cualquier otra función interna. Las variables definidas en func
no son accesibles desde este scope.
def func():
var_local_func = 10
var_local_func
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
Cell In[42], line 1
----> 1 var_local_func
NameError: name 'var_local_func' is not defined
El
scope
por defecto es un ámbito especial de Python que se crea o carga cada vez que ejecutas un script o abres una sesión interactiva. Este ámbito contiene nombres como palabras clave, funciones, excepciones y otros atributos que están incorporados en Python. Los nombres en este ámbito de Python también están disponibles desde cualquier parte de tu código. Es cargado automáticamente por Python cuando ejecutas un programa o script.
# Scope global
True
# Scope no local
def func():
True
# Scope local
def func():
def func2():
True
func2()
Una de las cosas importantes es que los nombres que se encuentran en un scope determinado puede ser accedidos desde un scope externo pero no pueden ser actualizados o modificados
contador = 0
def actualizar_contador():
contador += 1
actualizar_contador()
---------------------------------------------------------------------------
UnboundLocalError Traceback (most recent call last)
Cell In[55], line 1
----> 1 actualizar_contador()
Cell In[54], line 2, in actualizar_contador()
1 def actualizar_contador():
----> 2 contador += 1
UnboundLocalError: local variable 'contador' referenced before assignment
3. Sentencias global
y nonlocal
global
y nonlocal
Teniendo en cuenta el comportamiento por defecto que hemos visto en los apartados anteriores, Python nos proporciona las dos sentencias global
y nonlocal
para modificarlo si lo necesitásemos.
contador = 0
def actualizar_contador():
global contador
contador += 1
actualizar_contador()
contador
1
def funcion():
contador = 0
def actualizar_contador():
nonlocal contador
contador += 1
actualizar_contador()
print(contador)
funcion()
1
Última actualización