Effective Python Learning Memorandum Day 6 [6/100]

Introduction

The other day I learned about 100 Days Of Code, which was popular on Twitter for a while. The purpose of this article is to keep a record and output how much I, as a beginner, can grow through 100 days of study. I think there are many mistakes and difficult to read. I would appreciate it if you could point out!

Teaching materials to be learned this time

Today's progress

--Progress: Pages 56-60 --Chapter 3: Classes and Inheritance ――I will write down what I often forget or didn't know about what I learned today.

Use helper classes rather than record management in dictionaries and tuples

Records management using dictionaries and tuples is easy to use, but when it becomes complicated, readability is significantly reduced. As an example, define a class that records the sales of a store.

class SimpleSalesRecord(object):
    def __init__(self):
        self._record = {}
    
    def add_shop_id(self, shop_id):
        self._record[shop_id] = []

    def report_record(self, shop_id, price):
        self._record[shop_id].append(price)

    def average_price(self, shop_id):
        records = self._record[shop_id]
        return sum(records) / len(records)

record = SimpleSalesRecord()
record.add_shop_id(111)
record.report_record(111, 90)
record.report_record(111, 80)
print(record.average_price(111))

Output result

850.0

Consider extending this class to manage sales by product.

class ByitemSalesRecord(object):
    def __init__(self):
        self._record = {}
    
    def add_shop_id(self, shop_id):
        self._record[shop_id] = {}         #Change from list to dictionary

    def report_record(self, shop_id, item, price):
        by_item = self._record[shop_id]
        record_list = by_item.setdefault(item, [])
        record_list.append(price)

    def average_price(self, shop_id):
        by_item = self._record[shop_id]
        total, count = 0, 0
        for prices in by_item.values():
            total += sum(prices)
            count += len(prices)
        return total / count

record = ByitemSalesRecord()
record.add_shop_id(111)                     # shop_Added a store with id 111
record.report_record(111, 'Apple', 100)     #Added 111 store sales
record.report_record(111, 'Apple', 120)     #Added 111 store sales

print(record.average_price(111))   #Calculate average sales of 111 stores

Output result

Apple: 110.0
Orange: 90.0

In addition, we will implement a function to discount those with a near expiration date.

class DiscountSalesRecord(object):
    def __init__(self):
        self._record = {}
    
    def add_shop_id(self, shop_id):
        self._record[shop_id] = {}         #Change from list to dictionary

    def report_record(self, shop_id, item, price, weight):
        by_item = self._record[shop_id]
        record_list = by_item.setdefault(item, [])
        record_list.append((price, weight))

    def average_price(self, shop_id):
        by_item = self._record[shop_id]
        price_sum, price_count = 0, 0
        for item, prices in by_item.items():
            item_avg, total_weight = 0, 0
            for price, weight in prices:
                price_sum += price * weight
                price_count += 1
        return price_sum / price_count

record = DiscountSalesRecord()
record.add_shop_id(111)                          # shop_Added a store with id 111
record.report_record(111, 'Apple', 100, 0.8)     #It's not clear what the positional arguments mean
record.report_record(111, 'Apple', 120, 1) 
print(record.average_price(111))                 #Calculate average sales of 111 stores

In the average_price method, there is a loop inside the loop, which makes it difficult to read. When this complexity arises, it's time to shift from dictionaries and tuples to the class hierarchy.

Refactoring to class

The code that refactored the above code into a class is as follows. The named tuple of the collection module is different from a normal tuple and can be specified by a keyword argument.

import collections

Record = collections.namedtuple('Record', ('price', 'weight'))

class Item(object):
    def __init__(self):
        self._records = []

    def report_record(self, price, weight=1):
        self._records.append(Record(price, weight))

    def average_price(self):
        total, total_weight = 0, 0
        for record in self._records:
            total += record.price * record.weight
        return total / len(self._records)

class Shop_ID(object):
    def __init__(self):
        self._shop_items = {}

    def item(self, name):
        if name not in self._shop_items:
            self._shop_items[name] = Item()
        return self._shop_items[name]

    def average_price(self):
        total, count = 0, 0
        for shop_item in self._shop_items.values():
            total += shop_item.average_price()
            count += 1
        return total / count

class SalesRecord(object):
    def __init__(self):
        self._shop_id = {}

    def shop_id(self, name):
        if name not in self._shop_id:
            self._shop_id[name] = Shop_ID()
        return self._shop_id[name]

record = SalesRecord()
shop_111 = record.shop_id(111)
apple = shop_111.item('Apple')
apple.report_record(100, 0.8)
apple.report_record(100)
print(shop_111.average_price())

Summary

--Do not create dictionaries whose values ​​are other dictionaries or long tuples --Change to use multiple helper classes when the dictionary becomes complicated

Recommended Posts

Effective Python Learning Memorandum Day 15 [15/100]
Effective Python Learning Memorandum Day 6 [6/100]
Effective Python Learning Memorandum Day 12 [12/100]
Effective Python Learning Memorandum Day 9 [9/100]
Effective Python Learning Memorandum Day 8 [8/100]
Effective Python Learning Memorandum Day 14 [14/100]
Effective Python Learning Memorandum Day 1 [1/100]
Effective Python Learning Memorandum Day 13 [13/100]
Effective Python Learning Memorandum Day 3 [3/100]
Effective Python Learning Memorandum Day 5 [5/100]
Effective Python Learning Memorandum Day 4 [4/100]
Effective Python Learning Memorandum Day 7 [7/100]
Effective Python Learning Memorandum Day 2 [2/100]
Python learning day 4
Python memorandum
Python Memorandum 2
Python memorandum
python learning
python memorandum
python memorandum
Python day 1
Python memorandum
python memorandum
Python memorandum
Python basics memorandum
[Python] Learning Note 1
Python learning notes
Python pathlib memorandum
Python memorandum (algorithm)
python learning output
Deep Learning Memorandum
Python learning site
Python Deep Learning
Python learning (supplement)
Deep learning × Python
Python memorandum [links]
python learning notes
Python study day 1
Machine learning starting with Python Personal memorandum Part2
Machine learning starting with Python Personal memorandum Part1
Python class (Python learning memo ⑦)
Learning Python with ChemTHEATER 03
"Object-oriented" learning with python
Python module (Python learning memo ④)
Reinforcement learning 1 Python installation
Learning Python with ChemTHEATER 05-1
Python: Deep Learning Practices
Python ~ Grammar speed learning ~
python memorandum (sequential update)
Python: Unsupervised Learning: Basics
Learning record 4 (8th day)
Learning record 9 (13th day)
[1day1lang AdventCalender] day4 Python
Learning record 3 (7th day)
Learning record 5 (9th day)
Learning record 6 (10th day)
Python memorandum (personal bookmark)
Programming learning record day 2
Learning record 8 (12th day)
Learning record 1 (4th day)
Learning record 7 (11th day)