Initial commit

This commit is contained in:
David Beazley
2023-07-16 20:21:00 -05:00
parent 82e815fab2
commit 7d4b30154a
259 changed files with 600233 additions and 2 deletions

49
Solutions/5_2/reader.py Normal file
View File

@@ -0,0 +1,49 @@
# reader.py
from abc import ABC, abstractmethod
import csv
import logging
log = logging.getLogger(__name__)
class CSVParser(ABC):
def parse(self, filename):
records = []
with open(filename) as f:
rows = csv.reader(f)
headers = next(rows)
for rowno, row in enumerate(rows, start=1):
try:
record = self.make_record(headers, row)
records.append(record)
except ValueError as e:
log.warning('Row %d: Bad row: %s', rowno, row)
log.debug('Row %d: Reason: %s', rowno, e)
return records
@abstractmethod
def make_record(self, headers, row):
raise NotImplementedError()
class DictCSVParser(CSVParser):
def __init__(self, types):
self.types = types
def make_record(self, headers, row):
return { name: func(val) for name, func, val in zip(headers, self.types, row) }
class InstanceCSVParser(CSVParser):
def __init__(self, cls):
self.cls = cls
def make_record(self, headers, row):
return self.cls.from_row(row)
def read_csv_as_dicts(filename, types):
parser = DictCSVParser(types)
return parser.parse(filename)
def read_csv_as_instances(filename, cls):
parser = InstanceCSVParser(cls)
return parser.parse(filename)

51
Solutions/5_2/stock.py Normal file
View File

@@ -0,0 +1,51 @@
# stock.py
class Stock:
__slots__ = ('name','_shares','_price')
_types = (str, int, float)
def __init__(self, name, shares, price):
self.name = name
self.shares = shares
self.price = price
def __repr__(self):
# Note: The !r format code produces the repr() string
return f'{type(self).__name__}({self.name!r}, {self.shares!r}, {self.price!r})'
def __eq__(self, other):
return isinstance(other, Stock) and ((self.name, self.shares, self.price) ==
(other.name, other.shares, other.price))
@classmethod
def from_row(cls, row):
values = [func(val) for func, val in zip(cls._types, row)]
return cls(*values)
@property
def shares(self):
return self._shares
@shares.setter
def shares(self, value):
if not isinstance(value, self._types[1]):
raise TypeError(f'Expected {self._types[1].__name__}')
if value < 0:
raise ValueError('shares must be >= 0')
self._shares = value
@property
def price(self):
return self._price
@price.setter
def price(self, value):
if not isinstance(value, self._types[2]):
raise TypeError(f'Expected {self._types[2].__name__}')
if value < 0:
raise ValueError('price must be >= 0')
self._price = value
@property
def cost(self):
return self.shares * self.price
def sell(self, nshares):
self.shares -= nshares