Recuerde que una variable es una etiqueta para una ubicación en la memoria.
Puede utilizarse para contener un valor.
En los "static typed languages", las variables tienen tipos predeterminados, y una variable sólo puede usarse para almacenar valores de ese tipo.
En Python, podemos reutilizar la misma variable para almacenar valores de cualquier tipo.
Para definir una nueva variable en Python, simplemente asignamos un valor a una etiqueta.
x = 0
Si intentamos acceder al valor de una variable que aún no ha sido definida en ninguna parte, el intérprete saldrá con un error de nombre
No todas las variables son accesibles desde todas las partes de nuestro programa, y no todas las variables existen el mismo tiempo.
Dónde es accesible una variable y cuánto tiempo existe depende de cómo se defina.
Por ejemplo, una variable definida dentro de una función muere una vez que la función terminó de ejecutarse.
Llamamos scope a la parte del programa donde una variable es accesible, y lifetime a la duración de su existencia.
Scope: reglas de búsqueda de una variable en un programa
Regla: LEGB
: Local, Enclosing, Globa, Builtin
Conocer estas reglas:
Permite escribir programas más fiables
Disminuir bugs
Poder comprender la estructura de ejecución de un programa
En programación, el scope de un nombre define el área de un programa en la que se puede acceder inequívocamente a ese nombre, como variables, funciones, objetos, etc.
Un nombre sólo será visible y accesible por el código en su scope
Dos tipos de scope generales:
Una variable definida en el cuerpo principal de un file se denomina variable global.
Será visible en todo el file, y también dentro de cualquier file que importe ese fichero.
Las variables globales pueden tener consecuencias no deseadas debido a sus amplios efectos - por eso casi nunca deberíamos usarlas.
Sólo los objetos que están destinados a ser utilizados as globals, como las funciones y clases, deben ser puestos en el espacio de nombres global.
Una variable definida dentro de una función es local a esa función.
Es accesible desde el momento en que se define hasta el final de la función, y existe mientras la función se esté ejecutando.
Los nombres de los parámetros en la definición de la función se comportan como variables locales, pero contienen los valores que pasamos a la función cuando la llamamos.
Cuando utilizamos el operador de asignación (=) dentro de una función, su comportamiento por defecto es crear una nueva variable local - a menos que ya exista una variable con el mismo nombre definida en el ámbito local.
Every time a function is called, a local scope is created.
Local, Enclosing, Global, Built-in
Es la forma en que Python busca una variable... el orden de ámbito
Python comprueba primero las variables en el ámbito local, luego en el ámbito envolvente, luego en el global y finalmente en el build-in
x = 'global x'
x
es una variable global because it is in the main body of my script
def test():
x = 'local x'
print(x)
test()
print(x)
x
deontro de la función es una a local variable for the function test().
Cuando se llama a la función, print(x) busca dentro de la función su argumento x
, que es una variable... busca localmente y encuentra allí esta variable.
Qué pasa si introduzco x
dentro de la función y cambio la función, i.e, redefino las variables dentor de la función
def test():
y = 'local y'
print(y)
print(x)
test()
Como x
no existe en el local scope, lo busca en la siguiente etapa, el global scope.
Una primera cuestión importante es que las variables locales no viven fuera de la funcion.
def test():
y = 'local y'
# print(y)
print(x)
test()
print(y)
Pero la variable global la puedo llamar tanto fuera como dentro de la función.
def test():
y = 'local y'
# print(y)
print(x)
test()
print(x)
Puedo darle el mismo nombre a un local y a una global variable, pero la local no existe fuera de la función.
def test():
x = 'local x'
# print(y)
print(x)
test()
print(x)
Important: read what happend: there is one local x and one global x
Miremos a las direcciones a las que se refieren las variables
def test():
x = 'local x'
# print(y)
print(id(x))
test()
print(id(x))
La variable x local solo vive dentro de la funcion. Existe la posiblidad de incluir un global x en la función. Pero esto puede complicar la programación
x = 'global x'
print(f"Id global x: {id(x)}")
print(f"x global antes de modificar x: {x}")
def test():
global x
x = 'local x'
# print(y)
print(f"Id local x: {id(x)}")
print(f"x local x: {x}")
test()
print(f"x global modificada dentro de la f: {x}")
Si emprimimos locals()
dentro de una función, aparecen las variables locales.
def test(z):
#x = 'local x'
# print(y)
print(locals())
print(z)
test('local z')
El argumento z
es local tb.
Los argumentos de una funcion son locales.
Enclosing scope Tiene que ver con inner and outer functions
def outer():
x = 'outer x'
def inner():
x = 'inner x'
print(x)
inner()
print(x)
outer()
Cuando se llama a outer(), el primer x
es local para el outer function
Cuando llamo a inner(), busca x
locales en inner
Ahora comentemos el x
del inner
def outer():
x = 'outer x'
def inner():
#x = 'inner x'
print(x)
inner()
print(x)
outer()
Esto es el enclosing: busca la x
in any of the enclosing functions
El mismo concepto de global y local se aplica en las funciones
Podemos decirle a la función que queremos trabajar con la x global en el enclosing scope.
nonlocal nos permite trabajar con variables locales de las enclosing functions y modificarlas
def outer():
x = 'outer x'
def inner():
nonlocal x
x = 'inner x'
print(x)
inner()
print(x)
outer()
Ejercicio: en los siguientes casos, cual es el resultado de correr estos programas
a = 0
def my_function():
print(a)
my_function()
a = 0
def my_function():
a = 3
print(a)
my_function()
print(a)
a = 0
def my_function():
print(a)
a = 3
my_function()
print(a)
Cuando el script encuentra def
define un objeto con el nombre de la función y crea las variables locales del lado derecho...las referencias, pero no las asigna hasta que la función es llamada.
Entonces, cuando lee print(a)
, dentro de la función, observa que nada se le ha asignado aún, por lo que dá un error.
a = 0
def my_function():
y = a + 3
print(f"a {a}")
print(f"y {y}")
my_function()
print(a)
Aquí solo la estamos referenciando...y como no la encuentra dentro del local scope va a buscarla fuera...no hay problema.
Pero observemos que pasa con este pequeño cambio donde definimos a
dentro de la función.
a = 0
def my_function():
y = a + 3
a = 3
print(f"a {a}")
print(f"y {y}")
my_function()
print(a)
# Posibilidad: usar global
a = 0
def my_function():
global a
print(a)
a = 3
my_function()
print(a)
Ejercicio: Analice los siguientes scripts
var = 1
def inc():
print(var)
inc()
var = 1
def inc():
var = var + 1
print(var)
inc()
var = 0
def inc():
y = var
y = y + 1
print(var)
print(y)
inc()