6.0 KiB
6.0 KiB
Genetic 类技术文档
概述
Genetic 是一个用于实现属性遗传机制的基类,支持对象之间的父子关系建立,并允许子对象继承父对象的属性。该设计模拟了一种类似原型继承的机制,适用于需要层级化属性共享与继承的场景。
通过 __parent__ 和 __children__ 两个特殊属性维护对象间的树状结构,子对象在访问自身不存在的属性时,会自动向上追溯其父对象,直到根节点。
类定义
class Genetic:
"""
A Base class for genetical objects,
all the instances can inherit attributes from its parent.
"""
功能特点
- 支持动态属性继承(从父对象获取未定义的属性)
- 维护双向父子关系(父 → 子 和 子 → 父)
- 可构建多层对象继承树
- 易于扩展:其他类可继承
Genetic获得遗传能力
属性说明
| 属性名 | 类型 | 描述 |
|---|---|---|
__parent__ |
Genetic 或 None |
当前对象的父对象。初始为 None。 |
__children__ |
List[Genetic] |
当前对象的所有子对象列表。初始为空列表。 |
⚠️ 注意:这两个属性是私有属性(双下划线命名),不应直接修改,应通过提供的方法管理。
方法说明
__init__(self)
初始化一个新的 Genetic 实例。
行为:
- 设置
self.__parent__ = None - 初始化
self.__children__ = []
示例:
obj = Genetic()
print(obj.__parent__) # 输出: None
print(obj.__children__) # 输出: []
__getattr__(self, name)
重写 Python 的属性访问机制。当尝试访问对象中不存在的属性时触发。
参数:
name(str):要访问的属性名
返回值:
- 父对象中的对应属性值(递归查找)
异常:
- 若父链终止且仍未找到属性,则抛出
AttributeError
查找逻辑:
- 首先检查当前对象的
__dict__是否包含该属性 - 若无,且存在父对象,则递归调用
getattr(parent, name) - 若无父对象仍找不到,抛出
AttributeError
✅ 提示:此机制实现了“属性冒泡”式继承。
示例:
parent = Genetic()
parent.x = 100
child = Genetic()
child.setParent(parent)
print(child.x) # 输出: 100(从父继承)
addChild(self, child)
将指定对象添加为当前对象的一个子对象,并设置其父引用。
参数:
child(Genetic):要添加的子对象实例
行为:
- 将
child添加到self.__children__列表 - 设置
child.__parent__ = self
注意事项:
- 不检查重复或类型,调用者需确保传入有效的
Genetic子类实例 - 建立的是双向链接
setParent(self, parent)
设置当前对象的父对象,等价于让父对象执行 addChild(self)。
参数:
parent(Genetic):希望设定为父的对象
行为:
- 调用
parent.addChild(self) - 自动完成父子关系绑定
示例:
p = Genetic()
c = Genetic()
c.setParent(p) # c 成为 p 的子对象
使用示例
以下是一个完整示例,展示如何使用 Genetic 构建四层对象树并进行属性继承:
if __name__ == '__main__':
class A(Genetic):
def __init__(self, a1, a2):
Genetic.__init__(self)
self.a1 = a1
self.a2 = a2
class B(Genetic):
def __init__(self, b):
Genetic.__init__(self)
self.b = b
# 创建对象
gp = A(1, 2) # 祖先
p = B(3) # 父
c = A(4, 5) # 子
gc = B(6) # 孙子
# 建立遗传链:gp → p → c → gc
gc.setParent(c)
c.setParent(p)
p.setParent(gp)
# 测试属性继承
print(gc.a1) # 输出: 1 (从 gp 继承)
print(gc.b) # 输出: 3 (从 p 继承)
print(c.a2) # 输出: 2 (从 gp 继承)
结构图解
gp (A: a1=1, a2=2)
└── p (B: b=3)
└── c (A: a1=4, a2=5)
└── gc (B: b=6)
尽管 gc 自身没有定义 a1,但由于继承链的存在,它可以通过 __getattr__ 向上查找直至 gp 获取 a1=1。
设计原理与适用场景
核心思想
- 原型式继承:类似于 JavaScript 的原型链,对象可以直接从另一个对象继承属性。
- 运行时动态继承:继承关系在实例化后仍可更改(如更换父对象)。
- 轻量级属性共享:避免冗余数据复制,适合配置传播、上下文传递等场景。
典型应用场景
- 配置系统:高层配置向下继承,低层可覆盖
- UI 组件树:样式/主题继承
- 游戏开发:角色状态、技能树继承
- DSL 或规则引擎:上下文环境逐层传递
注意事项与限制
| 项目 | 说明 |
|---|---|
| ❌ 循环引用风险 | 不应形成闭环(如 A→B→A),否则 __getattr__ 可能导致无限递归 |
| ⚠️ 属性覆盖逻辑 | 当前仅支持“向上查找”,不支持同名属性优先级控制(即无法区分是否显式定义) |
| 📦 私有属性限制 | 双下划线属性(如 __x)会被 Python 名称改写,可能导致继承失效 |
| 🔁 多重继承不支持 | 当前模型仅为单亲继承,不处理多个父对象的情况 |
扩展建议
- 添加
hasattr_recursive()方法判断属性是否可继承 - 实现
removeChild()/clearParent()来解除关系 - 增加事件通知机制(如
on_parent_changed) - 支持只读继承或深拷贝模式
总结
Genetic 类提供了一个简洁而强大的对象属性继承框架,利用 Python 的 __getattr__ 魔法方法和父子引用机制,实现了灵活的运行时属性共享。适合作为基础组件集成进需要层次化数据管理的系统中。
💡 “不是所有对象都需要基因,但一旦拥有,传承便有了意义。”