如何基于现有类创建可按层类型与下标访问的蛋糕类?
实现支持下标与类名访问的蛋糕分层对象
需要将多个预定义类(如Frosting、Bread、Filling)的实例组合成一个新对象,要求同时支持两种访问方式:
- 通过下标访问各层实例
- 通过层的类名直接访问对应实例
现有预定义类代码:
class Frosting(object): def __init__(self, Size, flavor): self.Size = Size self.flavor = flavor class Bread(object): def __init__(self, Size, flavor): self.Size = Size self.flavor = flavor class Filling(object): def __init__(self, Size, flavor): self.Size = Size self.flavor = flavor
当前仅能通过列表下标访问:
layer0 = Bread(10, 'Vanilla') layer1 = Frosting(5, 'Chocolate') newCake = [layer0, layer1] # 仅能通过下标访问:newCake[1].flavor
期望实现BuildCake类,达成如下使用效果:
CakeFoo = BuildCake(newCake) print(CakeFoo.Frosting.flavor) # 输出Chocolate print(CakeFoo[0].flavor) # 输出Vanilla
解决方案
实现BuildCake类时,需要完成两个核心逻辑:
- 存储所有层实例,支持下标访问(通过实现
__getitem__魔法方法) - 将每个层实例按类名绑定为对象属性(通过
setattr动态设置)
基础实现(单类单实例场景)
class BuildCake(object): def __init__(self, layers): # 存储所有层的列表,用于下标访问 self.layers = layers # 遍历每个层,将类名作为属性绑定到当前对象 for layer in layers: layer_class_name = type(layer).__name__ setattr(self, layer_class_name, layer) # 实现下标访问的魔法方法 def __getitem__(self, index): return self.layers[index]
测试验证
layer0 = Bread(10, 'Vanilla') layer1 = Frosting(5, 'Chocolate') CakeFoo = BuildCake([layer0, layer1]) # 通过类名访问 print(CakeFoo.Frosting.flavor) # 输出: Chocolate # 通过下标访问 print(CakeFoo[0].flavor) # 输出: Vanilla
扩展:支持同类型多实例场景
如果蛋糕存在多个同类型层(比如两层Frosting),基础实现会导致后面的实例覆盖前面的。可以修改逻辑,将同类型实例存储为列表:
class BuildCake(object): def __init__(self, layers): self.layers = layers # 初始化一个字典存储类名到实例列表的映射 self.layer_map = {} for layer in layers: layer_class_name = type(layer).__name__ if layer_class_name not in self.layer_map: self.layer_map[layer_class_name] = [] self.layer_map[layer_class_name].append(layer) # 绑定属性:如果只有一个实例则直接赋值,否则赋值为列表 if len(self.layer_map[layer_class_name]) == 1: setattr(self, layer_class_name, layer) else: setattr(self, layer_class_name, self.layer_map[layer_class_name]) def __getitem__(self, index): return self.layers[index]
多实例场景测试
layer0 = Bread(10, 'Vanilla') layer1 = Frosting(5, 'Chocolate') layer2 = Frosting(3, 'Strawberry') CakeFoo = BuildCake([layer0, layer1, layer2]) print(CakeFoo.Frosting[0].flavor) # 输出: Chocolate print(CakeFoo.Frosting[1].flavor) # 输出: Strawberry print(CakeFoo[2].flavor) # 输出: Strawberry
内容的提问来源于stack exchange,提问作者Robert Simpson
相关产品推荐
相关产品推荐

