Enumerar comprensiones con objetos de clase

Nov 26 2020

Tengo una clase llamada StrucData en subfile.py

class StrucData:  
def __init__(self, name):
    self.name=name

def loadData(self, size=1, cost=1):
    self.size=size  
    self.cost=cost

En el archivo principal yo:

  1. llamar al subarchivo,
  2. crear una lista de nombres de datos
  3. recorrer la lista para crear una instancia de los objetos; y
  4. cargar datos usando el método 'loadData' para cada objeto (estoy usando el mismo 'tamaño' y 'costo' para facilitar este ejemplo).
    from subfile import StrucData 

    listIndex=['data1','data2','data3']

    # Create a list of objects
    listObjects=[]

    # Iterate through the list of objects
    for i in range(3):
        data=StrucData(listIndex[i])
        data.loadData(size=3, cost=4)
        listObjects.append(data)

Lo que estoy tratando de hacer es hacer lo mismo usando la comprensión de listas, para obtener

listObjects=[object1, object2, object3]

y he probado algo como

listObjects=[[StrucData(listIndex[i]) for k in range(3)] listObjects[i].loadData(size=3, cost=4) for i in range(3)]]

que no funciona, por supuesto, pero no sé cómo hacerlo correctamente.

¿Podría darme un consejo sobre mi código para obtener los resultados deseados utilizando una lista de comprensión?

Respuestas

1 BillHuang Nov 26 2020 at 19:00

Si puede agregar return selfa la última línea de StrucData.loadData()inside subfile.py, podría simplificarse así:

# in the main file
listObjects = [StrucData(idx).loadData(size=3, cost=4) for idx in listIndex]

De lo contrario, debe hacer esto por separado porque loadData()no devolverá nada para una expresión de comprensión de lista.

listObjects = [StrucData(idx) for idx in listIndex]
for i in range(3):
    listObjects[i].loadData(size=3, cost=4)
2 DavidFrancosCuartero Nov 26 2020 at 19:26

Complementando la respuesta de Bill Huang, si no tiene la libertad de cambiar el objeto y no desea iterar dos veces, puede agregar una función auxiliar:

def load_data(idx, size, cost):
    result = StructData(idx)
    result.loadData(size, cost)
    return result

[load_data(x, size=3, cost=4) for x in range(3)]

Como nota al margen, si realmente no necesita que la instancia tenga el nombre y loadData separados, puede usar una tupla con nombre:

from collections import namedtuple

StructData = namedtuple('StructData', ['name', 'size', 'cost'])
print([StructData(name=x, size=3, cost=4) for x in range(3)])

Que volvería:

[StructData(name=0, size=3, cost=4), 
 StructData(name=1, size=3, cost=4), 
 StructData(name=2, size=3, cost=4)]

Finalmente, dado que tiene nombres como "data1", "data2", es posible que desee tenerlos como nombres de clase, puede hacerlo con namedtuple siempre que los nombres sean identificadores de clase válidos:

from collections import namedtuple

list_index = ['data1', 'data2', 'data3']
print([namedtuple(name, ['size', 'cost'])(3, 4) for name in list_index])

Resultado:

[data1(size=3, cost=4), data2(size=3, cost=4), data3(size=3, cost=4)]