I have a class representing items of stock and their value:
class stock:
def __init__(self, stockName, stockType, value):
self.name = stockName
self.type = stockType
self.value = value
I have loads of stock so I make a list of stock objects from which I can access the value of individual items e.g stockList[12].value
I want to add up the value of all stock items which are 'shirts'. The following works fine:
shirtValue = sum([s.value for s in stockList if s.value == 'shirt'])
OK, fine. But now I have a list of stockType
and wish to sum the value of items which match a particular entry in the stockType list e.g.:
stockTypeValue[0] = sum([s.value for s in stockList if s.value == stockType[0]])
where stockType[0] = 'shirt'
This doesn't work. I know Why - it is because in Python 3 list comprehensions have their own scope (See detailed answer here: Accessing class variables from a list comprehension in the class definition )
My question is this: The code I have written, which I think would work in Python 2 looks great, it is clean, easy to understand, and to the untrained eye looks very pythonic.
But I can't figure out how to do the same thing in a nice pythonic way in Python 3. I'm going back to big loop structures.
What is the best way to do this in Python 3?
* Edit * Error messages:
Here is an example of what I am trying to do:
stockList=[]
stockList.append(stock('product A', 'shirt', 53.2))
stockList.append(stock('product B', 'hat', 20.2))
sum([s.value for s in stockList if s.type=='shirt'])
output:
Out[5]: 53.3
But if I put 'shirt' into a variable:
stockType = 'shirt'
sum([s.value for s in stockList if s.type==stockType])
output:
Traceback (most recent call last):
File "<console>", line 1, in <module>
File "<console>", line 1, in <listcomp>
NameError: name 'stockType' is not defined
This doesn't work. I know Why - it is because in Python 3 list comprehensions have their own scope (See detailed answer here: Accessing class variables from a list comprehension in the class definition )
That’s actually not true. I mean, of course that answer in that question is correct but that’s not what is happening here. That question is only relevant for expressions that happen in the class body at definition time. If you are e.g. within a method though then there is no problem at all.
However, what likely fails (“likely” because you didn’t supply the error message), is that the target list stockTypeValue
isn’t initialized.
>>> stockTypeValue[0] = 'something'
Traceback (most recent call last):
File "<pyshell#4>", line 1, in <module>
stockTypeValue[0] = 'something'
NameError: name 'stockTypeValue' is not defined
So we can define it now and assign an empty list; but the list is still empty:
>>> stockTypeValue = []
>>> stockTypeValue[0] = 'something'
Traceback (most recent call last):
File "<pyshell#6>", line 1, in <module>
stockTypeValue[0] = 'something'
IndexError: list assignment index out of range
Instead, you would have to append the result to the empty list:
>>> stockTypeValue.append('something')
>>> stockTypeValue[0]
'something'
Replaying your example:
>>> stockList = []
>>> stockList.append(stock('product A', 'shirt', 53.2))
>>> stockList.append(stock('product B', 'hat', 20.2))
>>> sum([s.value for s in stockList if s.type == 'shirt'])
53.2
>>> stockType = 'shirt'
>>> sum([s.value for s in stockList if s.type == stockType])
53.2
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With