Slots es el camino a seguir:
La forma pitónica es usar tragamonedas en lugar de jugar con el __setter__
. Si bien puede resolver el problema, no mejora el rendimiento. Los atributos de los objetos se almacenan en un diccionario " __dict__
", esta es la razón por la que se pueden agregar atributos dinámicamente a los objetos de las clases que hemos creado hasta ahora. Usar un diccionario para el almacenamiento de atributos es muy conveniente, pero puede significar una pérdida de espacio para los objetos, que tienen solo una pequeña cantidad de variables de instancia.
Las tragamonedas son una buena forma de solucionar este problema de consumo de espacio. En lugar de tener un dictado dinámico que permite agregar atributos a los objetos de forma dinámica, los espacios proporcionan una estructura estática que prohíbe las adiciones después de la creación de una instancia.
Cuando diseñamos una clase, podemos usar slots para evitar la creación dinámica de atributos. Para definir ranuras, debes definir una lista con el nombre __slots__
. La lista debe contener todos los atributos que desee utilizar. Demostramos esto en la siguiente clase, en la que la lista de ranuras contiene solo el nombre de un atributo "val".
class S(object):
__slots__ = ['val']
def __init__(self, v):
self.val = v
x = S(42)
print(x.val)
x.new = "not possible"
=> No crea un atributo "nuevo":
42
Traceback (most recent call last):
File "slots_ex.py", line 12, in <module>
x.new = "not possible"
AttributeError: 'S' object has no attribute 'new'
NÓTESE BIEN:
- Desde Python 3.3, la ventaja de optimizar el consumo de espacio ya no es tan impresionante. Con Python 3.3 , los diccionarios de uso compartido de claves se utilizan para el almacenamiento de objetos. Los atributos de las instancias son capaces de compartir parte de su almacenamiento interno entre sí, es decir, la parte que almacena las claves y sus correspondientes hashes. Esto ayuda a reducir el consumo de memoria de los programas, que crean muchas instancias de tipos no integrados. Pero todavía es el camino a seguir para evitar atributos creados dinámicamente.
- El uso de las tragamonedas también tiene su propio costo. Romperá la serialización (por ejemplo, pickle). También romperá la herencia múltiple. Una clase no puede heredar de más de una clase que define ranuras o tiene un diseño de instancia definido en código C (como lista, tupla o int).
__setattr__
pero probablemente sería un truco.