Ver los problemas que puede crear un argumento default mutables
Ver cómo resolverlo
Entender cómo o cuando se evalua una función.
Objetos mutables e inmutables
-Cada variable en Python contiene una instancia de un objeto.
-Hay dos tipos de objetos en Python: objetos mutables e inmutables.
-Cada vez que un objeto es instanciado, se le asigna un id de objeto único.
-El tipo del objeto se define en tiempo de ejecución y no se puede cambiar después.
-Sin embargo, su estado puede cambiarse si es un objeto mutable.
Inmutables: objetos que no los puedo cambiar una vez que los cree, e.g., float, tuple (aunque una tuple puede contener objetos mutables)
Mutables: objetos que, una vez creados, puedo modificar su estado.
Vamos a ver esto en PythonTutor
a = [1, 2, 3]
print(id(a))
a.append(4)
print(id(a))
b = a
print(b)
a.append(5)
print(a)
print(b)
a = 3
print(id(a))
b = a
print(id(b))
a = 4
print(a)
print(b)
print(id(a))
# Veamos que pasa cuando definimos una función
# con un objeto mutable
a = [1,2,3]
def appl(x):
a.append(x)
return a
b = appl(4)
print(a)
print(b)
print(id(a))
print(id(b))
b.append(5)
print(a)
#Vamos a cambiar el código
a = [1,2,3]
def bppl(x):
b = a
print(id(b))
b.append(x)
return b
c = bppl(4)
print(a)
print(c)
print(id(a))
print(id(c))
print(b)
#Vamos a cambiar el código:
# ver que cree un nuevo objeto
a = [1,2,3]
def bppl(x):
b = a.copy()
print(id(b))
b.append(x)
return b
c = bppl(4)
print(a)
print(c)
print(id(a))
print(id(c))
print(b)
## Mutable arguments
## Vamos a definir una función que agregue
## nombres a una lista
def add_name(name, name_list = []):
name_list.append(name)
print(name_list)
nombres = ["pepe", "ana"]
add_name("juan", nombres)
# Que pasaría si no incluyo la lista
add_name("juan")
add_name("Maria")
Lo que está pasando es que el default
está cambiando.
Si no ingreso una lista, la lista default se modifica e incluye los nombres anteriores, por se un objeto mutable.
def add_name(name, name_list = []):
name_list.append(name)
print(name_list)
Escribir en orden, en Pythontutor,para ver como va cambiando el default ````python def add_name(name, name_list = []): name_list.append(name) print(name_list)
print(add_name.defaults) c = add_name("juan") print(add_name.defaults) d = add_name("maria") print(add_name.defaults)
Para corregirlo, se sustituye el objeto mutable de la función de la siguiente manera
def add_name(name, name_list = None):
if name_list == None:
name_list = []
name_list.append(name)
print(name_list)
add_name.__defaults__
add_name("maria")
add_name.__defaults__
import time
from datetime import datetime
def reloj(time_p = datetime.now()):
print(time_p.strftime("%B %d, %Y %H:%M:%S"))
# Default value that will be set every time
# we run the function
reloj.__defaults__
El valor por defecto se evalúa una sola vez cuando se crea la función, y se establece en ese valor cada vez que llamamos a la función
reloj.__defaults__
reloj()
time.sleep(5)
reloj.__defaults__
reloj()
time.sleep(5)
reloj.__defaults__
reloj()
def reloj(time_p = None):
if time_p is None:
time_p = datetime.now()
print(time_p.strftime("%B %d, %Y %H:%M:%S"))
reloj.__defaults__
reloj()
time.sleep(5)
reloj.__defaults__
reloj()
time.sleep(5)
reloj.__defaults__
reloj()