[pyar] Modificación de clases e instancias

Alejandro Santos listas en alejolp.com
Vie Sep 9 06:10:48 ART 2016


2016-08-31 17:21 GMT+02:00 Javier Burroni <javier.burroni en gmail.com>:
> El código es solamente para probar la idea:
> https://gist.github.com/jburroni/0a2db81ba541e1d8dc632368fd7f8982 pero me
> interesa saber si hay alguna solución standard
>

No, porque hay diferencias fundamentales entre Python y Smalltalk. Lo
que vos queres hacer no es standar.

1. Las variables de instancia de las instancias de objetos son
propiedad la instancia, no de la clase. En Python las variables de
instancia no son creadas por la clase. El metodo __init__ se encarga
de crear las variables de instancia y la instancia puede elegir que
variables de instancia tener, y cuales son. Si queres que una
instancia ya creada tenga nuevas variables de instancia necesitas, a
cada instancia, agregarle o modificarle sus variables.

>>> class X: pass
...
>>> a = X()
>>> a.b = 1
>>> a.x = 1
>>> b = X()
>>> b.y = 2
>>> a.y
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: X instance has no attribute 'y'
>>> b.x
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: X instance has no attribute 'x'
>>> b.y
2
>>> a.x
1
>>> dir(a)
['__doc__', '__module__', 'b', 'x']
>>> dir(b)
['__doc__', '__module__', 'y']
>>>

2. Incluso usando New Style Classes (lo default en Python 3) con
__slots__ las instancias siempre referencian a la clase original de la
que fueron creadas. Cuando modificas una clase lo que haces es crear
una nueva clase, no modificas la original. El atributo __class__ de
una intancia te devuelve la referencia a la clase de la instancia. Si
bien el nombre es el mismo, son dos clases diferentes.

$ python3
Python 3.5.2 (default, Jul  5 2016, 12:43:10)
[GCC 5.4.0 20160609] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> class Y:
...     __slots__ = ('x', 'w',)
...
>>>
>>> a = Y()
>>> a.x = 1
>>> a.y = 2
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'Y' object has no attribute 'y'
>>> class Y:
...     __slots__ = ('x', 'w', 'y')
...
>>> a.y
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'Y' object has no attribute 'y'
>>> a.y = 1
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'Y' object has no attribute 'y'
>>> a.__class__
<class '__main__.Y'>
>>> id(a.__class__)
43672840
>>> Y
<class '__main__.Y'>
>>> id(Y)
46161352
>>> b = Y()
>>> dir(b)
['w', 'x', 'y']
>>> dir(a)
['w', 'x']

Fijate que Y no tiene __init__.

-- 
Alejandro Santos


Más información sobre la lista de distribución pyar