yufiP
yufiP

Reputation: 113

List comprehensions with class objects

I have a class named StrucData in subfile.py

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

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

In the main file I:

  1. call the subfile,
  2. create a list of data names
  3. loop through the list to instantiate the objects; and
  4. load data using 'loadData' method for each object (I'm using the same 'size' and 'cost' to make this example easy.)
    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)

What I am trying to do is doing the same thing using list comprehension, to obtain

listObjects=[object1, object2, object3]

and I have tried something like

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

which doesn't work of course, but I don't know how to do it properly.

Could I please have advice on my code to obtain the desired outputs using a list comprehension??

Upvotes: 1

Views: 1674

Answers (2)

David Francos Cuartero
David Francos Cuartero

Reputation: 193

Complementing Bill Huang's response, if you're not free to change the object and you don't want to iterate twice, you could add a helper function:

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)]

As a side-note, if you don't really need the instance to have the name and loadData separated, you could just use a namedtuple:

from collections import namedtuple

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

Wich would return:

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

Finally, seeing that you have names such as "data1", "data2", you might want to have that as classnames, you can do so with namedtuple as long as names are valid class identifiers:

from collections import namedtuple

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

Result:

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

Upvotes: 2

Bill Huang
Bill Huang

Reputation: 4658

If you are free to append return self to the last line of StrucData.loadData() within subfile.py, it could be simplified like this:

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

Otherwise, you have to do this separately because loadData() won't return anything for a list comprehension expression.

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

Upvotes: 1

Related Questions