1

I have an object

class Car:
  def __init__(self):
    price = float(0)

Then another

class Day:
  def __init__(self):
    self.carList = [Car() for each in range(100)]
    self.createPriceList()

  def createPriceList(self):
    tempCar = Car()
    for i in range(100):
      tempCar.price = function_giving_a_value() # 10 last cars have 0.0 as value
      self.carList[i] = tempCar
      print i, self.carList[i].price 
# prints the correct list : each line contains a correct price
#edited after answers : in fact it's just misleading, cf answers

  def showPriceList(self):
    for i in range(len(self.carList)):
      print i, self.carList[i].price 
# prints i (correct) but each self.carList[i].price as 0.0
# so len(self.carList) gives correct value, 
# but self.carList[i].price a wrong result

My question is :

  • Why in showPriceList(), self.carList is correctly recognized (len gives the correct number in looping) but self.carList[i].price gives only zeros? (when it seems correctly filled in method createPriceList())
user1097922
  • 61
  • 2
  • 2
  • 4

3 Answers3

4

The most likely explanation is that you don't actually call createPriceList() before calling showPriceList(). [edit: now that you've edited the code in your question, we can eliminate this possibility]

Also, createPriceList() has an error whereby you assign references to the same Car object to all elements of the list. This error could also explain the behaviour, if and only if the last random() function_giving_a_value() call returns zero.

Finally, you're missing self. in a couple of places [edit: again, you seem to have fixed some of these in a recent edit].

Here is how I would have written it:

import random

class Car:

    def __init__(self, price):
        self.price = price

class Day:

  def __init__(self, n):
      self.carList = []
      for i in range(n): # could also use list comprehension here
          self.carList.append(Car(random.random()))

  def printPriceList(self):
      for i, car in enumerate(self.carList):
        print(i, car.price)

day = Day(20)
day.printPriceList()
NPE
  • 486,780
  • 108
  • 951
  • 1,012
  • 2
    Did you look at the code of `createPriceList()`? It sets all items of the list to the same object. – Sven Marnach Dec 14 '11 at 14:41
  • @SvenMarnach: Yes, I was typing that into my answer as you were typing your question :-) – NPE Dec 14 '11 at 14:42
  • Ah, I see. Still very surprising that `random.random()` returns exactly zero. :) – Sven Marnach Dec 14 '11 at 14:45
  • well, in fact createPriceList() was called in __init__ (my mistake creating this code example). and in my example i used random() first but in real code it's not random() but a function giving a price. this function works fine, tested. – user1097922 Dec 14 '11 at 15:27
  • you're right, only reference was assigned, so when i changed value of tempCar.price, it changed for all "items" in list. thx all for your precious help. i was stuck all day on it ! – user1097922 Dec 14 '11 at 15:54
  • The OP code is wrong because he creates a single instance of `theCar` object and adds that object to his list. Any change on that object is reflected in all its "views" which are all the list elements. – jsbueno Dec 15 '11 at 14:06
  • @jsbueno: I take it you've read the second paragraph of my answer? – NPE Dec 15 '11 at 14:32
0

First of all, you're using the for loop in a 'wrong' way. You're creating an index from the length of a list, and then accesing elements from that same list using this index. This can be simplified, take for example your createPriceList method, it could look like this:

def createPriceList(self):
    for car in self.carList
        car.price = random()
        print car.price

What you did in your example, is create one car before the loop, and changing it's value every time you store the car. That means that your carlist will be filled with references to the same car, so they will all have the same price.

The zeros are because random() returns a floating point number between 0 and 1. If this number is smaller then 0.1, the printed version will look like 0.0

bigblind
  • 12,539
  • 14
  • 68
  • 123
  • hum i'm not sure because : print i, self.carList[i].price returns really what i want : each line shows a different price. – user1097922 Dec 14 '11 at 15:20
  • thats because you printed right after assigning the price. If you would prinr self.carList[i-1].price, you'd see that it prints the same value as self.carList[i] – bigblind Dec 14 '11 at 15:23
  • @ Creemers : you're totally right, self.carList[i-1].price prints same as self.carList[i].price – user1097922 Dec 14 '11 at 15:42
0

Depending on what you are trying to acheive, it might be better to keep single attributes for single Car()s, and build a list of Car() instances outside of the class:

import random

class Car:
    def __init__(self):
        self.price = random.random()

class Day:
    def __init__(self):
        self.cars = [Car() for each in range(100)]

day = Day()
priceList = [car.price for car in day.cars]

The priceList should not exist within the class since it is redundant, in my opinion.

Benjamin
  • 11,560
  • 13
  • 70
  • 119