I am running into some problems with subclassing.
I need to create a class that inherits list properties but I need the returned list (self.tiles_pool) to be one that is created when the class is constructed. The list is generated by an external CSV file. I tried creating the class without inheritance but quickly realized there was no way to return my list without creating a separate method to do so. But I need the instance of the class to be a list object (i.e. print the generated list when I print the object). The class is for creating a Tile Pool like the bag of letter tiles in scrabble.
If there is some way of returning my list (self.tiles_pool) without inheritance and without using user defined methods that would be better.
Here is my code so far:
import csv
import random
class TilePool(list):
def __init__(self):
list.__init__(self)
# Open csv file
with open("tiles.csv") as f:
# Read csv into list of lists of each lines values
tiles_csv = csv.reader(f, delimiter=",")
# Convert the list into a tile pool
self.tiles_pool = [(line[0], line[1])
for line in tiles_csv if len(line[0]) == 1
for x in xrange(int(line[2]))]
del tiles_csv
def pop(self, tile_count=None):
assert len(self.tiles_pool) > 0, "# Tile Pool is empty"
if tile_count is None:
tile_count = 7
assert tile_count in xrange(1, 8), "# Tile Count must be between 1 and 7"
new_tiles = []
counter = 1
while len(self.tiles_pool) > 0 and counter <= tile_count:
rand_choice = random.choice(self.tiles_pool) # Get a random tile
new_tiles.append(rand_choice) # Add it to new_tiles list
self.tiles_pool.remove(rand_choice) # Delete it from pool
counter += 1
return new_tiles
def view_pool(self):
if len(self.tiles_pool) == 0:
print("# Tile Pool is empty")
else:
for tile in self.tiles_pool:
print("{letter}: {score}".format(letter=tile[0], score=tile[1]))
print len(self.tiles_pool)
I understand that this implementation may seem strange and I could probably just put this in a function but I am under instruction to make it a class. Any help or advice would be much appreciated. Thanks.
Why subclass list
if you don't use it? self
is the list you want, there is no need to create a tiles_pool
. Since lists can be initialized with a sequence, delay parent __init__
until you can feed it the csv. Your code does some things I don't understand such as duplicating tiles line[2]
times, but I figure you know what you are doing there.
In this sample, I remove tiles_pool
in favor of using self
and do a few other tweaks like using the "truthiness" of lists (bool([1]) is True
while bool([]) is False
) instead of using len
but it should work the same as the original.
import csv
import random
class TilePool(list):
def __init__(self):
with open("tiles.csv") as f:
tiles_csv = csv.reader(f, delimiter=",")
list.__init__(self, (line[0:2]
for line in tiles_csv if len(line[0]) == 1
for x in xrange(int(line[2]))))
def pop(self, tile_count=None):
# non-empty list is truthy
assert self, "# Tile Pool is empty"
if tile_count is None:
tile_count = 7
assert tile_count in range(1, 8), "# Tile Count must be between 1 and 7"
new_tiles = []
counter = 1
while self and counter <= tile_count:
rand_choice = random.choice(self) # Get a random tile
new_tiles.append(rand_choice) # Add it to new_tiles list
self.remove(rand_choice) # Delete it from pool
counter += 1
return new_tiles
def view_pool(self):
if not self:
print("# Tile Pool is empty")
else:
for tile in self:
print("{letter}: {score}".format(letter=tile[0], score=tile[1]))
print len(self)
t = TilePool()
t.pop(3)
t.view_pool()