Reputation: 11
When I call the classmethod within the init , where I initialize an object, the classmethod count_genre is called each time, incrementing values that were there before. I'd only like to call the method once.
class Furniture:
materials = []
material_count = {}
def __init__(self, name, material):
self.name = name
self.material = material
Furniture.materials.append(self.material)
Furniture.count_material()
@classmethod
def count_material(cls):
for material in cls.materials:
cls.material_count[material] = cls.material_count.get(material, 0) + 1
Furniture("Chair", "Wood")
Furniture("Cushion", "Cotton")
Furniture("Table", "Glass")
print(Furniture.material_count)
This is what I get on my terminal: {'Chair': 3, 'Cushion': 2, 'Table': 1}
This is what I want to get: {'Chair': 1, 'Cushion': 1, 'Table': 1}
Upvotes: 0
Views: 68
Reputation: 17
here it is following the logic of your question plus with your last question to my answer:
class Furniture:
materials = set()
material_count = {}
def __init__(self, name: str, material: str):
self.name = name
self.material = material
Furniture.materials.add(self.material)
Furniture.count_material(self.material)
@classmethod
def count_material(cls, material):
if material in cls.material_count:
cls.material_count[material] += 1
else:
cls.material_count[material] = 1
Furniture("Chair", "Wood")
Furniture("Cushion", "Cotton")
Furniture("Table", "Glass")
Furniture("Cushion", "Cotton")
print(Furniture.material_count) # {'Wood': 1, 'Cotton': 2, 'Glass': 1}
Upvotes: 0
Reputation: 17
The problem is that the material is added to the BOM every time a new piece of furniture is created and all the materials in the BOM are counted. This means that if you create several pieces of furniture with the same material, that material will be counted multiple times.
A simple solution would be to use an assembly instead of a list for the materials, which will automatically eliminate any duplicates. You can then convert the assembly to a list before counting the materials.
Here is the logic to solve it:
Define the Furniture class with two class attributes: materials and material_count. materials is an array that will store the unique materials used in the furniture, and material_count is a dictionary that will store the count of each material.
Define the init method that is executed when a new Furniture object is created. This method adds the material of the new object to the material set and then calls the count_material method.
Defines the count_material class method that updates the material_count dictionary to contain the count of each material in the materials set. Since materials is an assembly, each material will only be counted once, no matter how many Furniture objects use it.
Create some furniture and print the material_count dictionary to verify that each material has been counted only once. Code:
class Furniture:
materials = set()
material_count = {}
def __init__(self, name: str, material: str):
self.name = name
self.material = material
Furniture.materials.add(self.material)
Furniture.count_material()
@classmethod
def count_material(cls):
cls.material_count = {material: 1 for material in cls.materials}
Furniture("Chair", "Wood")
Furniture("Cushion", "Cotton")
Furniture("Table", "Glass")
print(Furniture.material_count) # {'Cotton': 1, 'Wood': 1, 'Glass': 1}
Upvotes: 0
Reputation: 531055
Use Furniture
to model a piece of furniture. Use a separate class to model information about a particular set of pieces of furniture.
import dataclass
import collections
@dataclasses.dataclass
class Furniture:
name: str
material: str
class FurnitureCollection:
def __init__(self):
self.material_count = collections.Counter()
self.pieces = []
def add(self, f: Furniture):
self.pieces.append(f)
self.material_count[f.material] += 1
@property
def materials(self):
return list(self.material_count)
fc = FurnitureCollection()
fc.add(Furniture("Char", "Wood"))
fc.add(Furniture("Cushion", "Cotton"))
fc.add(Furniture("Table", "Glass"))
assert fc.material_count["Wood"] == 1
assert all(x in fc.materials for x in ["Wood", "Cotton", "Glass"])
Upvotes: 1