¿Cómo combinas objetos personalizados en Python para crear una colección que mantenga la interfaz de los objetos subyacentes?
Tengo un grupo de objetos en Python que me gustaría sumar sin perder acceso a la funcionalidad implementada en los objetos.
Para ilustrar el punto, considera esta clase:
class PlaneTicket:
def __init__(self, origin:str, destination:str):
...
def price(self, pricingDate:date)->float:
'''Returns the best price available on a given date'''
...
En mi aplicación, necesito poder sumar estos objetos. Puedes pensarlo como tener que crear un viaje que requiere dos boletos de avión.
flight1 = PlaneTicket('london', 'new-york')
flight2 = PlaneTicket('new-york', 'paris')
journey = flight1 + flight2
Ahora, lo interesante es que también quiero poder usar los métodos en los objetos subyacentes. Por ejemplo:
journey.price('2021-06-19')
Debería ser igual a la suma de (flight.price(‘2021-06-19’) for flight in journey.flights)
Entonces, podríamos implementar una clase Journey
y hacer que la suma de objetos PlaneTicket
sea un objeto Journey
, y también implementar un .price
en la clase Journey
.
Sin embargo, puede que esté perdiendo una mejor solución ya que estoy seguro de que este es un problema común. Además, necesitaría diferentes implementaciones de la clase Journey
si estoy sumando, promediando o multiplicando los objetos PlaneTicket
.
Supongo que la formulación general sería:
- Tengo una colección de objetos que implementan un método
foo()
. - Quiero agregar estos objetos (por ejemplo, sumándolos).
- Quiero poder llamar a
foo
en la agregación y tener los valores de retorno de los objetos constituyentes agregados.
davy.ai
Una solución a este problema es utilizar el método
__add__
de la clasePlaneTicket
para devolver una nueva clase que agregue los precios de los dos billetes. Esta nueva clase también puede almacenar referencias a los objetosPlaneTicket
subyacentes, lo que nos permite llamar a sus métodosprice
en la claseJourney
.Aquí hay una implementación de ejemplo:
Con esta implementación, ahora podemos crear un objeto
Journey
sumando objetosPlaneTicket
:Y podemos llamar al método
price
en el objetoviaje
para obtener el precio total:También podemos llamar al método
price
en los objetosPlaneTicket
subyacentes accediendo al atributotickets
del objetoJourney
:Esta implementación nos permite agregar fácilmente objetos
PlaneTicket
y seguir accediendo a su funcionalidad subyacente. También podemos crear diferentes clases para diferentes tipos de agregaciones (por ejemplo,JourneyAverage
), si es necesario.