En Python, ¿cómo es posible reutilizar objetos existentes inmutables iguales (como se hace para str
)? ¿Se puede hacer esto simplemente definiendo un método __hash__
, o requiere medidas más complicadas?¿Reutilizar objetos existentes para objetos inmutables?
Respuesta
Si desea crear mediante el constructor de la clase y hacer que devuelva un objeto creado previamente, deberá proporcionar un método __new__
(porque para cuando llegue a __init__
el objeto ya se ha creado).
Aquí está un ejemplo sencillo - si el valor que se utiliza para inicializar se ha visto antes de esa fecha un objeto creado previamente se devuelve en lugar de crear uno nuevo:
class Cached(object):
"""Simple example of immutable object reuse."""
def __init__(self, i):
self.i = i
def __new__(cls, i, _cache={}):
try:
return _cache[i]
except KeyError:
# you must call __new__ on the base class
x = super(Cached, cls).__new__(cls)
x.__init__(i)
_cache[i] = x
return x
Tenga en cuenta que para este ejemplo se puede usar cualquier cosa para inicializar mientras sea hashable Y solo para mostrar que los objetos realmente se están reutilizando:
>>> a = Cached(100)
>>> b = Cached(200)
>>> c = Cached(100)
>>> a is b
False
>>> a is c
True
Gracias.Esto funcionó, la única diferencia que usé fue así: 'clase a (objeto): _cached = {}
@Abafei: Sí, su cambio es bueno. A mucha gente le gusta evitar los argumentos predeterminados mutables, ya que a menudo confunden a los demás. No soy tan considerado :) –
Tenga en cuenta que '__init__' se llamará * dos veces * cuando hay una falta de caché y una vez si hay un golpe de caché . Necesita proteger explícitamente contra múltiples llamadas de constructor, p. establece una bandera al final de '__init__' y regresa inmediatamente si se establece la bandera. – kynan
Creo que tendrías que mantener un dict {args: object} de instancias ya creadas, luego anular el método de clase '__new__
para verificar ese diccionario y devolver el objeto relevante si ya existía. Tenga en cuenta que no he implementado o probado esta idea. Por supuesto, las cadenas se manejan en el nivel C.
Sí esto funciona: he utilizado este método con éxito anteriormente. Puedo publicar un código de ejemplo mañana si nadie me gana. –
Existen dos soluciones de "ingeniería de software" para esto que no requieren ningún conocimiento de bajo nivel de Python. Se aplican en las siguientes situaciones:
Primer escenario: Los objetos de su clase son 'iguales' si están construidos con los mismos parámetros de constructor, y la igualdad no cambiará con el tiempo después de la construcción. Solución: Uso una fábrica que hashses los parámetros del constructor:
class MyClass:
def __init__(self, someint, someotherint):
self.a = someint
self.b = someotherint
cachedict = { }
def construct_myobject(someint, someotherint):
if (someint, someotherint) not in cachedict:
cachedict[(someint, someotherint)] = MyClass(someint, someotherint)
return cachedict[(someint, someotherint)]
Este enfoque limita esencialmente las instancias de la clase a un objeto único para cada par de entrada distinta. También hay inconvenientes obvios: no todos los tipos son fáciles de manipular, etc.
Segundo escenario: Los objetos de su clase son mutables y su "igualdad" puede cambiar con el tiempo. Solución: definen un registro de nivel de clase de la igualdad de casos:.
class MyClass:
registry = { }
def __init__(self, someint, someotherint, third):
MyClass.registry[id(self)] = (someint, someotherint)
self.someint = someint
self.someotherint = someotherint
self.third = third
def __eq__(self, other):
return MyClass.registry[id(self)] == MyClass.registry[id(other)]
def update(self, someint, someotherint):
MyClass.registry[id(self)] = (someint, someotherint)
En este ejemplo, los objetos con el mismo someint, someotherint
par son iguales, mientras que el tercer parámetro no tiene en cuenta El truco es mantener los parámetros en registry
en sincronía. Como alternativa al update
, puede reemplazar getattr
y setattr
para su clase; esto garantizaría que cualquier asignación foo.someint = y
se mantendría sincronizada con su diccionario de nivel de clase. Vea un ejemplo here.
- 1. Agregar objetos a objetos existentes
- 2. Serialización y objetos inmutables
- 3. Los objetos inmutables .net
- 4. Creación de objetos inmutables utilizandoJAXB
- 5. deshacer/rehacer con objetos inmutables
- 6. Creación de objetos emparejados inmutables
- 7. ¿Qué son los objetos inmutables?
- 8. ¿Es seguro reutilizar objetos javax.xml.ws.Service?
- 9. Objetos de Python de objetos existentes usando __new__
- 10. Creación de objetos inmutables de javabean
- 11. ¿Los objetos inmutables son una buena práctica?
- 12. ¿Cómo manipulo un árbol de objetos inmutables?
- 13. ¿Cómo crear objetos inmutables en C#?
- 14. Bloquear objetos mutables como inmutables en python
- 15. Los objetos inmutables con inicializadores de objeto
- 16. ¿Por qué los objetos Joda son inmutables?
- 17. Objetos de valor inmutables y JPA
- 18. Diferencia entre objetos mutables e inmutables
- 19. ¿Por qué debería reutilizar objetos XmlHttpRequest?
- 20. ¿Por qué los objetos inmutables son seguros para subprocesos?
- 21. Convención de nombres Scala para "setters" en objetos inmutables
- 22. ¿Cuál es el mejor enfoque para convertir objetos inmutables en objetos mutables (recursivos)?
- 23. ¿Qué usa Collection.Contains() para verificar si hay objetos existentes?
- 24. Patrón de objetos inmutables en C#: ¿qué piensas?
- 25. Objetos funcionales inmutables en el dominio altamente mutable
- 26. objetos inmutables Scala y rasgos con val campos
- 27. ¿No son inmutables los objetos String en Java?
- 28. Objetos inmutables en Java y acceso a datos
- 29. Reutilizar tipos existentes con ADO.NET Data Services
- 30. Cómo hacer que las colecciones inmutables de Scala contengan objetos inmutables
+1 Interesante pregunta. Sé por cadenas que el proceso se llama "internamiento", pero no estoy seguro de si ese término es específicamente para cadenas, ya que nunca he oído hablar de otra cosa siendo internado. – Davy8
A menudo, la función hash se implementará como la dirección del objeto, por lo que se obtiene un problema de huevo/gallina; el hash no será igual hasta que ya hayas decidido que los objetos son iguales. –