Python组合模式下如何保留列表结构并便捷访问元素属性?
实现A.B.C式批量属性访问的方案
核心思路是自定义一个继承自list的容器类,通过重载__getattr__方法,让容器在被访问属性时,自动遍历内部所有元素并收集对应属性的值,替代重复的列表推导式。
代码实现示例
1. 基础版本(支持属性访问)
class Colony: def __init__(self, propertyA): self.propertyA = propertyA self.propertyB = propertyA * 2 # 示例其他属性 class ColonyList(list): def __getattr__(self, attr_name): # 遍历列表中所有元素,收集指定属性的值 return [getattr(item, attr_name) for item in self] class Population: def __init__(self): # 用ColonyList替代普通list初始化colonies self.colonies = ColonyList(Colony(1) for _ in range(10)) # 测试 myPop = Population() print(myPop.colonies.propertyA) # 输出: [1, 1, 1, 1, 1, 1, 1, 1, 1, 1] print(myPop.colonies.propertyB) # 输出: [2, 2, 2, 2, 2, 2, 2, 2, 2, 2]
2. 进阶版本(支持方法批量调用)
如果需要批量调用Colony的方法,可以扩展__getattr__,判断属性是否为可调用对象,返回一个包装函数:
class ColonyList(list): def __getattr__(self, attr_name): # 先尝试获取自身属性(避免覆盖list原有方法) try: return super().__getattr__(attr_name) except AttributeError: pass # 检查元素是否有该属性 if not hasattr(self[0], attr_name): raise AttributeError(f"'Colony' object has no attribute '{attr_name}'") attr = getattr(self[0], attr_name) if callable(attr): # 如果是方法,返回一个批量调用的函数 def batch_call(*args, **kwargs): return [getattr(item, attr_name)(*args, **kwargs) for item in self] return batch_call else: # 否则返回属性值列表 return [getattr(item, attr_name) for item in self] # 给Colony加一个方法 class Colony: def __init__(self, propertyA): self.propertyA = propertyA def multiply(self, factor): return self.propertyA * factor # 测试方法调用 myPop = Population() print(myPop.colonies.multiply(3)) # 输出: [3, 3, ..., 3]
注意事项
- 这个方案完全兼容普通list的所有操作(比如append、pop、切片等),因为ColonyList继承自list
- 如果某个Colony实例没有指定属性,会抛出
AttributeError,和直接访问单个Colony对象的行为一致,避免隐性错误 - 如果需要过滤空值或处理异常,可以在
__getattr__的列表推导式里添加判断逻辑,比如[getattr(item, attr_name) for item in self if hasattr(item, attr_name)]
内容的提问来源于stack exchange,提问作者Vítor Sudbrack
相关产品推荐
相关产品推荐

