Compreensões de listas com objetos de classe
Eu tenho uma classe chamada StrucData em subfile.py
class StrucData:
def __init__(self, name):
self.name=name
def loadData(self, size=1, cost=1):
self.size=size
self.cost=cost
No arquivo principal I:
- chame o subarquivo,
- crie uma lista de nomes de dados
- percorrer a lista para instanciar os objetos; e
- carregar dados usando o método 'loadData' para cada objeto (estou usando o mesmo 'tamanho' e 'custo' para tornar este exemplo fácil.)
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)
O que estou tentando fazer é fazer a mesma coisa usando a compreensão de lista, para obter
listObjects=[object1, object2, object3]
e eu tentei algo como
listObjects=[[StrucData(listIndex[i]) for k in range(3)] listObjects[i].loadData(size=3, cost=4) for i in range(3)]]
o que não funciona, é claro, mas não sei como fazer direito.
Posso ter conselhos sobre meu código para obter os resultados desejados usando uma compreensão de lista?
Respostas
Se você estiver livre para acrescentar return self
à última linha de StrucData.loadData()
dentro subfile.py
, pode ser simplificado assim:
# in the main file
listObjects = [StrucData(idx).loadData(size=3, cost=4) for idx in listIndex]
Caso contrário, você terá que fazer isso separadamente porque loadData()
não retornará nada para uma expressão de compreensão de lista.
listObjects = [StrucData(idx) for idx in listIndex]
for i in range(3):
listObjects[i].loadData(size=3, cost=4)
Complementando a resposta de Bill Huang, se você não está livre para alterar o objeto e não deseja iterar duas vezes, pode adicionar uma função 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 uma observação lateral, se você realmente não precisa que a instância tenha o nome e loadData separados, você pode usar apenas um namedtuple:
from collections import namedtuple
StructData = namedtuple('StructData', ['name', 'size', 'cost'])
print([StructData(name=x, size=3, cost=4) for x in range(3)])
Que retornaria:
[StructData(name=0, size=3, cost=4),
StructData(name=1, size=3, cost=4),
StructData(name=2, size=3, cost=4)]
Finalmente, vendo que você tem nomes como "dados1", "dados2", você pode querer ter isso como nomes de classe, você pode fazer isso com namedtuple, desde que os nomes sejam identificadores de classe 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)]