Reputation: 637
I'm Python newbie, and, as you can see, I'm trying to study Object programming. In the next code, I'm trying to model trucks that transport items: every item has an identifier and a weight. Tracks have max weight capacity. Look at the code below, than I will tell you the problem.
class Item():
'''
Class Item models an object transported in a supply chain
'''
def __init__(self, id, weight):
'''
Constructor of an object of class Item
:param id: Unique identifier of the Item
:param weight: the weight of the Item, expressed in Kg
'''
self.id = id
self.weight = weight
class Truck():
'''
Class Truck models a truck transporting Items
'''
def __init__(self, plate_number, capacity):
'''
Constructor of an object of class Truck
:param plate_number: Unique identifier of the Truck
:param capacity: maximum weight transportable by the Truck
'''
self.plate_number = plate_number
self.capacity = capacity
self.remaining_capacity = capacity
def load(self, items):
'''
This method allows to load a list of items into a truck if their
total weight is less that or equal to the remaining capacity of the truck.
If this is case, True is returned. Otherwise False is returned
:param items:
:return:
'''
total_load = 0
for item in items:
total_load += item.weight
if total_load > self.remaining_capacity:
print('out of range')
return False
else:
for item in items:
items.append(item)
self.remaining_capacity = self.remaining_capacity - item.weight
return True
a = Item('AAA01', 10)
b = Item('BBB01', 20)
c = Item('CCC01', 30)
truck_a = Truck('LE000A', 35)
truck_a.load([a, b])
print('Remaining capcity of Truck ', truck_a.plate_number, ' is ',truck_a.remaining_capacity)
In the load(items)
method of Trucks, you can see the command items.append(item)
: if that command is delated, the averall program works; if not, it goes in loop, but I can't image why.
EDIT
Using the next code, it seems to work, without changing the items.append(item)
statement:
class Item():
'''
Class Item models an object transported in a supply chain
'''
def __init__(self, id, weight):
'''
Constructor of an object of class Item
:param id: a unique code associated to the item
:param weight: the weight of the item expressed in kg
'''
self.id = id
self.weight = weight
class Truck():
'''
This class models a truck
'''
def __init__(self, plate_number, capacity, items):
'''
Clonstructor of an object of class Truck
:param plate_number: a unique number Identifying the truck
:param capacity: maximum weight that the truck can carry
:param items: list of objects of class Item carried by the truck
'''
self.plate_number = plate_number
self.capacity = capacity
self.items = list(items)
self.remaining_capacity = capacity
for item in self.items:
self.remaining_capacity = self.remaining_capacity - item.weight
def load(self, items):
'''
This method allows to load a list of items into a truck if their
total weight is less that or equal to the remaining capacity of the truck.
If this is case, True is returned. Otherwise False is returned
:param items:
:return:
'''
total_load = 0
for item in items:
total_load = item.weight
if total_load > self.remaining_capacity:
return False
else:
for item in items:
self.items.append(item)
self.remaining_capacity = self.remaining_capacity - item.weight
return True
a = Item('AAA01', 10)
b = Item('BBB01', 20)
c = Item('CCC01', 30)
truck_a = Truck('LE000A', 35, [a])
truck_a.load([b])
print('Remaining capacity of Truck ', truck_a.plate_number, ' is ', truck_a.remaining_capacity)
As you can see, main difference in the EDIT code is that class Truck
has a constructor that takes items
as parameter and make a "copy" of it with the self.items = list(items)
. I don't know why this last code has been working
Upvotes: 0
Views: 784
Reputation: 7952
It appears to me like you're trying to keep a record of what is on the truck... you need to add a self.items
attribute and then append items to that:
def __init__(self, plate_number, capacity):
...
self.items = [] # Items on the truck
Then in load()
you can add items via self.items.append()
:
else:
for item in items:
self.items.append(item)
self.remaining_capacity = self.remaining_capacity - item.weight
return True
If you compare the runs of the following function on your first and second attempts, you'll see why:
def attributes(obj):
return [s for s in dir(obj) if s[0] != '_']
print attributes(truck_a)
in the first case, it won't have any items
list, because you didn't assign it one (self.items
). Once you do, it then has an attribute items
which can be accessed in the class via self.items
. This is different from the passed in parameter items
. You can make it less confusing by using different names:
def load(self, items_to_load):
...
for item_to_load in items_to_load:
self.items.append(item_to_load)
Upvotes: 2
Reputation: 1185
As mentioned in the previous comment and answer, you're iterating over the items in a list to which an item is being added each iteration, thereby generating an infinite loop. items += items
will work in this case, as mentioned. The general problem you're facing, however, is how to alter the items in a list while iterating over them. The best way is to iterate over a copy of the list, like so:
>>> items = [1, 2, 3]
>>> for item in items[:]:
items.append(item)
>>> items
[1, 2, 3, 1, 2, 3]
>>>
items[:]
is a slice of items
consisting of all members of items
, which is by definition a copy of items
. For dictionaries, which you cannot slice, use the copy()
method.
Upvotes: 1
Reputation: 77850
Your for loop alters the Instead, try this: list while it's iterating through the list. You can't ever get to the end, because you keep extending it while you work on it. What are you trying to do with the list items? If all you want is a list with the elements doubled, you can use
items += items
Here's a short illustration:
items = ["hello", 17, True]
for item in items:
items.append(item)
print items
Output:
['hello', 17, True, 'hello']
['hello', 17, True, 'hello', 17]
['hello', 17, True, 'hello', 17, True]
['hello', 17, True, 'hello', 17, True, 'hello']
['hello', 17, True, 'hello', 17, True, 'hello', 17]
['hello', 17, True, 'hello', 17, True, 'hello', 17, True]
...
Upvotes: 0