import math
def shape_density(thing: dict, weight: int | float) -> int | float:
return weight / call(thing, "area")
# our own __init__
def shape_new(name: str) -> dict:
return {"name": name, "_class": Shape}
Shape = {
"density": shape_density,
"_classname": "Shape",
"_parent": None,
"_new": shape_new,
}
def make(cls: dict, *args) -> dict:
return cls["_new"](*args)
def square_perimeter(thing: dict) -> int:
return thing["side"] * 4
def square_area(thing: dict) -> int:
return thing["side"] ** 2
def square_larger(thing: dict, size: int) -> bool:
return call(thing, "area") > size
def square_new(name: str, side: int | float) -> dict:
return make(Shape, name) | {"side": side, "_class": Square}
Square = {
"perimeter": square_perimeter,
"area": square_area,
"larger": square_larger,
"_classname": "Square",
"_parent": Shape,
"_new": square_new,
}
def circle_perimeter(thing: dict) -> int | float:
return math.pi * 2 * thing["radius"]
def circle_area(thing: dict) -> int | float:
return math.pi * thing["radius"] ** 2
def circle_larger(thing: dict, size) -> bool:
return call(thing, "area") > size
def circle_new(name: str, radius: int | float) -> dict:
return make(Shape, name) | {"radius": radius, "_class": Circle}
Circle = {
"perimeter": circle_perimeter,
"area": circle_area,
"larger": circle_larger,
"_classname": "Circle",
"_parent": Shape,
"_new": circle_new,
}
def find(cls: dict, method_name):
while cls is not None:
if method_name in cls:
return cls[method_name]
cls = cls["_parent"]
raise NotImplementedError(method_name)
def call(thing, method_name, *args):
method = find(thing["_class"], method_name)
return method(thing, *args)
examples = [make(Square, "sq", 3), make(Circle, "ci", 2)]
for shape in examples:
n = shape["name"]
p = call(shape, "perimeter")
a = call(shape, "area")
d = call(shape, "density", 10)
print(f"{n} has a perimeter of {p:.2f}, area {a:.2f} and density {d:.2f}")
size = 10
result = call(shape, "larger", size)
print(f"is {n} larger than {size}? {result}")