Anterior: No tengo ni puta idea | Siguiente: The light graffiti, parte I
Python no es C++
Python
Un viejo dicho reza que un programador puede escribir en Fortran en cualquier lenguaje de programación. Somos los que venimos precisamente de Fortran los que más tardamos en entender el verdadero significado de esta frase. Cada lenguaje de programación tiene sus peculiaridades, su filosofía. No ser consciente de todo lo que se esconde detrás de las estructuras puede acarrear bastantes dolores de cabeza. Veamos este ejemplo de código:
class inner(object):
l = list()
def append(self,item1,item2):
self.l.append((item1,item2))
class outer(object):
l1 = inner()
l2 = inner()
def __init__(self,item1,item2,item3,item4):
self.l1.append(item1,item2)
self.l2.append(item3,item4)
if __name__ == '__main__':
o = outer(1,2,3,4)
print o.l1.l
print o.l2.l
Definimos una pequeña clase llamada inner que sólo contiene un atributo, l, y un método, append. La clase outer contiene dos instancias de inner, a una se le añaden los items 1 y 2 y a la segunda se le añaden los items 3 y 4. ¿Qué sucede si ejecutamos el código?
[(1, 2), (3, 4)]
[(1, 2), (3, 4)]
Curiosamente o.l1 y o.l2 son iguales. Aunque hayamos utilizado el mismo método en instancias distintas, el atributo que se ha modificado es el mismo. ¿Tiene esto alguna lógica? Por supuesto.
Si en python se define alguna variable antes de __init__ esta variable será un atributo de clase, esto significa que será compartido por cualquier instancia sin importar donde se encuentre en el código. ¿Cómo especificar que o.l1 y o.l2 son dos instancias completamente distintas y que todos sus atributos son propios de la instancia? Veamos el segundo ejemplo:
class inner(object):
def __init__(self):
self.l = []
def append(self,item1,item2):
self.l.append((item1,item2))
class outer(object):
l1 = inner()
l2 = inner()
def __init__(self,item1,item2,item3,item4):
self.l1.append(item1,item2)
self.l2.append(item3,item4)
if __name__ == '__main__':
o = outer(1,2,3,4)
print o.l1.l
print o.l2.l
Ahora sí, cuando lo ejecutamos obtenemos:
[(1, 2)]
[(3, 4)]
En este segundo caso, la clase inner no tiene ningún atributo de clase, l es un atributo de instancia con lo que no es compartido en ningún caso.
Esta distinción viene dada por la diferencia entre clase e instancia que existe en los lenguajes interpretados. Cuando doy clase de Matlab insisto en que, en un lenguaje interpretado, no hay relación entre variable y tipo. Se trata del mismo concepto pero más complejo porque una clase suele ser más complicada que un número o un array.
-
Tags:
Ingeniería
Un viejo dicho reza que un programador puede escribir en Fortran en cualquier lenguaje de programación. Somos los que venimos precisamente de Fortran los que más tardamos en entender el verdadero significado de esta frase. Cada lenguaje de programación tiene sus peculiaridades, su filosofía. No ser consciente de todo lo que se esconde detrás de las estructuras puede acarrear bastantes dolores de cabeza. Veamos este ejemplo de código:
class inner(object):
l = list()
def append(self,item1,item2):
self.l.append((item1,item2))
class outer(object):
l1 = inner()
l2 = inner()
def __init__(self,item1,item2,item3,item4):
self.l1.append(item1,item2)
self.l2.append(item3,item4)
if __name__ == '__main__':
o = outer(1,2,3,4)
print o.l1.l
print o.l2.l
Definimos una pequeña clase llamada inner que sólo contiene un atributo, l, y un método, append. La clase outer contiene dos instancias de inner, a una se le añaden los items 1 y 2 y a la segunda se le añaden los items 3 y 4. ¿Qué sucede si ejecutamos el código?
[(1, 2), (3, 4)] [(1, 2), (3, 4)]
Curiosamente o.l1 y o.l2 son iguales. Aunque hayamos utilizado el mismo método en instancias distintas, el atributo que se ha modificado es el mismo. ¿Tiene esto alguna lógica? Por supuesto.
Si en python se define alguna variable antes de __init__ esta variable será un atributo de clase, esto significa que será compartido por cualquier instancia sin importar donde se encuentre en el código. ¿Cómo especificar que o.l1 y o.l2 son dos instancias completamente distintas y que todos sus atributos son propios de la instancia? Veamos el segundo ejemplo:
class inner(object):
def __init__(self):
self.l = []
def append(self,item1,item2):
self.l.append((item1,item2))
class outer(object):
l1 = inner()
l2 = inner()
def __init__(self,item1,item2,item3,item4):
self.l1.append(item1,item2)
self.l2.append(item3,item4)
if __name__ == '__main__':
o = outer(1,2,3,4)
print o.l1.l
print o.l2.l
Ahora sí, cuando lo ejecutamos obtenemos:
[(1, 2)] [(3, 4)]
En este segundo caso, la clase inner no tiene ningún atributo de clase, l es un atributo de instancia con lo que no es compartido en ningún caso.
Esta distinción viene dada por la diferencia entre clase e instancia que existe en los lenguajes interpretados. Cuando doy clase de Matlab insisto en que, en un lenguaje interpretado, no hay relación entre variable y tipo. Se trata del mismo concepto pero más complejo porque una clase suele ser más complicada que un número o un array.
