总结:自定义容器类的核心优势
| 场景 | 自定义People 类 | 普通列表 |
|---|---|---|
|
代码复用 |
✅ 方法一次定义,处处调用 |
❌ 逻辑重复,到处写 |
|
业务规则集中 |
✅ 添加、查找、过滤等规则封装在类内 |
❌ 规则散落在业务代码中 |
|
变更维护成本 |
✅ 修改只需改类内部 |
❌ 需全局搜索替换 |
|
团队协作 |
✅ 接口清晰,不易误用 |
❌ 依赖文档或口头约定 |
|
测试友好 |
✅ 可对 |
❌ 逻辑耦合在流程中,难测试 |
import json
from typing import List, Optional, Generator
class Person:
def __init__(self, name: str, age: int):
if not isinstance(name, str) or not name.strip():
raise ValueError("姓名必须是非空字符串")
if not isinstance(age, int) or age < 0:
raise ValueError("年龄必须是非负整数")
self.name = name.strip()
self.age = age
def __repr__(self):
return f"Person(name='{self.name}', age={self.age})"
def to_dict(self):
"""将 Person 转为字典,便于序列化"""
return {"name": self.name, "age": self.age}
class People:
def __init__(self, allow_duplicates: bool = True):
"""
初始化人群容器。
:param allow_duplicates: 是否允许同名人员(默认允许)
"""
self._persons: List[Person] = []
self._allow_duplicates = allow_duplicates
def add(self, person: Person) -> None:
"""
添加一个 Person 实例。
如果不允许重复姓名且已存在同名人员,则抛出 ValueError。
"""
if not isinstance(person, Person):
raise TypeError("只能添加 Person 类型的实例")
if not self._allow_duplicates:
if self.find_by_name(person.name) is not None:
raise ValueError(f"已存在名为 '{person.name}' 的人员,不允许重复添加。")
self._persons.append(person)
def find_by_name(self, name: str) -> Optional[Person]:
"""返回第一个匹配姓名的 Person,未找到返回 None"""
name = name.strip()
for p in self._persons:
if p.name == name:
return p
return None
def adults(self) -> Generator[Person, None, None]:
"""返回一个生成器,仅包含年龄 >=18 的 Person"""
return (p for p in self._persons if p.age >= 18)
def average_age(self) -> float:
"""计算平均年龄,若无人则返回 0.0"""
if not self._persons:
return 0.0
return sum(p.age for p in self._persons) / len(self._persons)
def to_json(self, indent: int = 2) -> str:
"""将所有人员转换为 JSON 字符串"""
data = [p.to_dict() for p in self._persons]
return json.dumps(data, ensure_ascii=False, indent=indent)
def __iter__(self):
"""支持 for person in people"""
return iter(self._persons)
def __len__(self):
"""支持 len(people)"""
return len(self._persons)
def __repr__(self):
"""开发者友好的字符串表示"""
return f"People({self._persons})"
def __bool__(self):
"""支持 if people: 判断是否为空"""
return len(self._persons) > 0
# ==================== 使用示例 ====================
if __name__ == "__main__":
# 创建人群(不允许同名)
people = People(allow_duplicates=False)
# 添加人员
people.add(Person("Alice", 30))
people.add(Person("Bob", 17))
people.add(Person("Charlie", 25))
# 尝试重复添加(会报错)
try:
people.add(Person("Alice", 28))
except ValueError as e:
print("❌ 添加失败:", e)
# 遍历所有人
print("👥 所有人员:")
for p in people:
print(p)
# 查找某人
alice = people.find_by_name("Alice")
print(f"\n🔍 找到 Alice: {alice}")
# 遍历成年人
print("\n🧑 成年人:")
for adult in people.adults():
print(adult)
# 平均年龄
print(f"\n📊 平均年龄: {people.average_age():.1f} 岁")
# 转 JSON
print("\n📄 JSON 输出:")
print(people.to_json())
# 其他功能
print(f"\n🔢 总人数: {len(people)}")
print(f"✅ 人群非空: {bool(people)}")

被折叠的 条评论
为什么被折叠?



