2026-02-16
bag:
The next step is to draw up a list of function names, method names, and operator symbols that meet the descriptions of these operations
Examples include:
- add
- clear
- count
- for ...
- in
- isEmpty
- len
- remove
- str
- +
- ==b and c refer to bagsb.clear() # Make the bag empty
for item in range(10): # Add 10 numbers to it
b.add(item)
print(b) # Print the contents (a string)
print(4 in b) # Is 4 in the bag?
print(b.count(2)) # 1 instance of 2 in the bag
c = b + b # Contents replicated in a new bag
print(len(c)) # 20 numbers
for item in c: # Print them all individually
print(item)
for item in range(10): # Remove half of them
c.remove(item)
print(c == b) #Should be the same contents now| User’s Bag Operation | Method in a Bag Class |
|---|---|
| b = |
init(self, sourceCollection=None) |
| b.add(item) | add(self, item) |
| b.clear() | clear(self) |
| b.count(item) | count(self, item) |
| b.isEmpty() | isEmpty(self) |
| b.remove(item) | remove(self, item) |
| len(b) | __len__(self) |
| str(b) | __str__(self) |
| for item in b | __iter__(self). |
| item in b | __contains__(self, item) Not needed if __iter__ is included |
| b1 + b2 | __add__(self, other) |
| b == anyObject | __eq__(self, other) |
<class name> is used in the table to indicate that this can be the name of any implementing bag class:
_init_remove method might raise a KeyError if the target item is not in the bagremove method:pass or return statement:
pass statement is used in the mutator methods that return no value, whereas each accessor method returns a simple default value, such as False, 0, or None"""
File: baginterface.py
Author: Ken Lambert
"""
class BagInterface(object):
"""Interface for all bag types."""
# Constructor
def __init__(self, sourceCollection = None):
"""Sets the initial state of self, which includes the
contents of sourceCollection, if it’s present."""
pass
# Accessor methods
def isEmpty(self):
"""Returns True if len(self) == 0,
or False otherwise."""
return True
def __len__(self):
"""Returns the number of items in self."""
return 0
def __str__(self):
"""Returns the string representation of self."""
return ""
def __iter__(self):
"""Supports iteration over a view of self."""
return None
def __add__(self, other):
"""Returns a new bag containing the contents
of self and other."""
return None
def __eq__(self, other):
"""Returns True if self equals other,
or False otherwise."""
return False
def count(self, item):
"""Returns the number of instances of item in self."""
return 0
# Mutator methods
def clear(self):
"""Makes self become empty."""
pass
def add(self, item):
"""Adds item to self."""
pass
def remove(self, item):
"""Precondition: item is in self.
Raises: KeyError if item in not in self.
Postcondition: item is removed from self."""
pass__init__ method)Array class or another array-based collection, such as Python’s list type__init__ method must deal with the possibility that its caller has provided a source collection parameter:
ArrayBag objectStep 1: Choose and Initialize the Data Structures
baginterface.py, and rename it to arraybag.pyArrayBag, add a class variable for the default capacity, and complete the __init__ method"""
File: arraybag.py
"""
from arrays import Array
class ArrayBag(object):
"""An array-based bag implementation."""
# Class variable
DEFAULT_CAPACITY = 10
# Constructor
def __init__(self, sourceCollection = None):
"""Sets the initial state of self, which includes the
contents of sourceCollection, if it’s present."""
self.items = Array(ArrayBag.DEFAULT_CAPACITY)
self.size = 0
if sourceCollection:
for item in sourceCollection:
self.add(item)IsEmpty, _len_, clear, and add# Accessor methods
def isEmpty(self):
"""Returns True if len(self) == 0, or False otherwise."""
return len(self) == 0
def __len__(self):
"""Returns the number of items in self."""
return self.size
# Mutator methods
def clear(self):
"""Makes self become empty."""
self.size = 0
self.items = Array(ArrayBag.DEFAULT_CAPACITY)
def add(self, item):
"""Adds item to self."""
# Check array memory here and increase it if necessary
self.items[len(self)] = item
self.size += 1Step 2:
self to get something done within a class definition, whenever possiblelen(self) instead of referring directly to the instance variable self.sizeadd method
add method places the new item at the logical end of the arrayStep 3:
__iter__ method maintains a cursor that allows it to navigate through a sequence of objects:
__iter__ method’s while loop terminatesdef __iter__(self):
"""Supports iteration over a view of self."""
cursor = 0
while cursor < len(self):
yield self.items[cursor]
cursor += 1yield keyword in Python is used in a function to make it a generator.yield allows you to use the object in a for loop, and each iteration retrieves the next item from the collection.__eq__ method follows the rules for the equality test discussed in Chapter 2__add__ method follows the rules for the concatenation of two collections discussed in Chapter 2__str__ method uses the map and join operations to build a string containing the string representations of the bag’s itemsdef __str__(self):
"""Returns the string representation of self."""
return "{" + ", ".join(map(str, self)) + "}"
# possible to use [] to wrap the collection instead of {} which is a set notation
def __add__(self, other):
"""Returns a new bag containing the contents
of self and other."""
result = ArrayBag(self)
for item in other:
result.add(item)
return result
def __eq__(self, other):
"""Returns True if self equals other,
or False otherwise."""
if self is other: return True
if type(self) != type(other) or \
len(self) != len(other):
return False
for item in self:
if self.count(item) != other.count(item):
return False
return Trueremove Methodremove method is the most challenging method to complete in the bag implementationremove Methoddef remove(self, item):
"""Precondition: item is in self.
Raises: KeyError if item in not in self.
postcondition: item is removed from self."""
# 1. check precondition and raise an exception if necessary
if not item in self:
raise KeyError(str(item) + " not in bag")
# 2. Search for index of target item
targetIndex = 0
for targetItem in self:
if targetItem == item:
break
targetIndex += 1
# 3. Shift items to the right of target left by one position
for i in range(targetIndex, len(self) - 1):
self.items[i] = self.items[i + 1]
# 4. Decrement logical size
self.size -= 1
# 5. Check array memory here and decrease it if necessary