Enumerar comprensiones con objetos de clase
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:
- llamar al subarchivo,
- crear una lista de nombres de datos
- recorrer la lista para crear una instancia de los objetos; y
- 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
Si puede agregar return self
a 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)
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)]