22
loading...
This website collects cookies to deliver better user experience
potencias = {}
for number in [2, 4, 16]:
potencias[number] = lambda x: number**x
print(potencias[2](4))
scope
y, para eso, voy a usar a Los Simpons. Vamos al lío.lambda
: Cuando haces lambda x: print(x)
esa lambda está definiendo un scope local en el que existe la variable x
.def
, estás creando un scope. En el siguiente código:
def my_function(param_1, param_2):
add = param_1 + param_2
return add
param_1
, param_2
y add
.class
, también se crea un scope. En este caso es un poco especial porque desde fuera sí puedes acceder al scope de la clase (más o menos). Así que vamos a dejar este caso aparte.def local_scope(a):
print(a)
local_scope("Hola") # >> "Hola"
local_scope
que contendría la variable a
.local_scope
, tendrás 100 scopes diferentes. Esto es así incluso si haces llamadas recursivas.def enclosing(param_out):
other_var = "HI"
def enclosed(param_in):
print(other_var)
print(param_out)
print(param_in)
return enclosed
enclosing
estaría definiendo el scope naranja y la enclosed
un scope dentro del anterior.>>> function_in = enclosing("Out")
>>> function_in("In")
HI
Out
In
>>> enclosed("In")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'enclosed' is not defined
super_global = "Estoy fuera de todo"
def my_function():
print(super_global)
def my_function_enclosing():
def my_function_enclosed():
print(super_global)
return my_function_enclosed()
>>> print(super_global)
Estoy fuera de todo
>>> my_function()
Estoy fuera de todo
>>> my_function_enclosing()
Estoy fuera de todo
super_global
porque sólo tienen que salir de habitaciones para ir a buscarla.len
, sorted
, max
...>>> lst = [1, 2, 3, 4, 5]
>>> len(lst)
5
len
en ninguna parte.my_var = "Hola"
estás añadiendo una nueva variable my_var
a tu scope.import
. Cuando tú haces import math
estás trayendo todo lo que haya en el scope global del módulo math
a tu scope. Por eso puedes usar funciones como sqrt
en tu scope solo si importas primero math
.var = "algo"
. Cuando haces:def func(param):
print(param)
param
al scope de la función func
aunque no estés asignándola a nada en ese momento. En el momento de la llamada se creará un scope para esa función y esa variable se creará automáticamente en el scope con el valor que haya recibido el parámetro.for number in range(1, 20):
print(number)
number
a scope global (si el for
lo tienes dentro de una función, lo añadirías a esa función).var = "Soy globalísima"
def modify():
var = "Soy localísima"
print(var)
>>> print(var)
Soy globalísima
>>> modify()
Soy localísima
>>> print(var)
Soy globalísima
def outter():
var = "Estoy fuerísima"
def inner():
var = "Estoy dentro del tó"
print(var)
print(var)
inner()
print(var)
>>> outter()
Estoy fuerísima
Estoy dentro del tó
Estoy fuerísima
var
en la función inner
, lo que estoy haciendo es declarar una variable nueva que hace shadowing
a la externa.potencias = {}
for number in [2, 4, 16]:
potencias[number] = lambda x: x**number
print(potencias[2](4))
number
que tiene como exponente será 2, en la segunda lambda será 4 y en la tercera 16.number
permanece definido como 16, pues es el último valor de la lista. Entonces cuando llamas a potencias[2]
se llama la primera lambda, en ese momento se crea un scope, y se busca number en el scope superior (el global) y, como es 16, al hacer potencias[2](4)
estamos haciendo
164
, que es nada más y nada menos que nuestro resultado, 65535.number
, el exponente, quede definida en el scope de la lambda en el momento de la creación, en vez de acceder a la del scope global.potencias = {}
for number in [2, 4, 16]:
potencias[number] = lambda x, number=number: x**number
print(potencias[2](4))
number
dentro de ese scope, que tomará por defecto el valor que tenga la variable del bucle homónima en ese momento. Por eso cuando llames a potencias[2](4)
, se creará un scope para esa función, pero con la variable number prefijada al valor que tenía en el momento de la creación de la lambda, pues ese valor por defecto es fijo.>>> print(potencias[2](4))
16
var = "Soy globalísima"
def modify():
var = "Soy localísima"
print(var)
var
dentro de la función. Hay una forma de modificar el scope de esa función para que esa variable se "enlace" bidireccionalmente con la del scope global.global
seguida del nombre de la variable que queremos enlazar con una global. Si bien vimos que el código anterior devolvía:>>> print(var)
Soy globalísima
>>> modify()
Soy localísima
>>> print(var)
Soy globalísima
var = "Soy globalísima"
def modify():
global var
var = "Soy localísima"
print(var)
>>> print(var)
Soy globalísima
>>> modify()
Soy localísima
>>> print(var)
Soy localísima
def outter():
var = "Estoy fuerísima"
def inner():
var = "Estoy dentro del tó"
print(var)
print(var)
inner()
print(var)
var
dentro de la función inner
. En este caso global
no nos sirve, pues estaríamos enlazando var
a una variable del scope global llamada var
, que no existe. Si intentamos hacer esto:def outter():
var = "Estoy fuerísima"
def inner():
global var
var = "Estoy dentro del tó"
print(var)
print(var)
inner()
print(var)
>>> outter()
Estoy fuerísima
Estoy dentro del tó
Estoy fuerísima
var
con el valor "Estoy dentro del tó", que no es lo que queremos.nonlocal
. Esto lo que hace es buscar la variable etiquetada como nonlocal
en el scope superior (y en el superior de ese, y así sucesivamente) y enlazarla de manera bidireccional igual que se hacía con global. Por tanto, si cambiamos el código a:def outter():
var = "Estoy fuerísima"
def inner():
nonlocal var
var = "Estoy dentro del tó"
print(var)
print(var)
inner()
print(var)
var
de inner, con la variable var
de outter y el resultado será:>>> outter()
Estoy fuerísima
Estoy dentro del tó
Estoy dentro del tó
nonlocal
busca en los scopes superiores de manera sucesiva hasta llegar al global. Si cuando llega al global no ha encontrado esa variable, dará un error. nonlocal
no permite enlazar una variable interna con una global, para eso tenemos la palabra global
. Un ejemplo:var = "Hola"
def func():
def inner():
nonlocal var
var = "Adios"
return inner()
File "<stdin>", line 3
SyntaxError: no binding for nonlocal 'var' found
var
a la que enlazar. Sin embargo al cambiar por global
:var = "Hola"
def func():
def inner():
global var
var = "Adios"
return inner()
for
ni un bucle while
definen un nuevo scope. Por tanto, cualquier variable que definas dentro de ellos seguirá viva fuera del bucle. Incluso la variable que definas en el bucle en sí!!for number in range(5):
print(number)
print(number)
0
1
2
3
4
>>> print(number)
4
number
sigue existiendo incluso después del bucle.if True:
var = "Hola"
print(var)
if True:
print(var)
Hola
Hola
[number for number in range(5)]
number
:>>> [number for number in range(5)]
[0, 1, 2, 3, 4]
>>> number
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'number' is not defined
try/except
podemos pensar que se van a comportar igual que un if
, pero hay una particularidad. Imagina el siguiente código:try:
a = 1
except Exception as e:
print("Error")
a
:>>> a
1
try:
raise ValueError()
except Exception as e:
print(e)
e
:>>> e
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'e' is not defined
e
, aunque se define en el except y se entra por ahí, no se crea en el scope.global
y nonlocal
.22