课程引入:继承的局限性
- 痛点场景:定义水池类,需包含乌龟和鱼 → 用继承/多继承逻辑混乱
- 解决方案:组合(横向整合无继承关系的类)
一、组合:类的横向整合
- 核心定义:把类的实例化放到新类中,实现类的组合
- 适用场景:多个类无纵向继承关系,是横向关联关系
- 代码实操(水池案例)
- 定义基础类:Turtle类(number属性)、Fish类(number属性)
- 定义组合类:Pool类(不继承,初始化传入乌龟数x、鱼数y)
- 组合核心操作:在Pool类中实例化基础类 → self.turtle = Turtle(x)、self.fish = Fish(y)
- 功能实现:print_number()方法,调用实例属性self.turtle.number和self.fish.number
- 核心优势:无继承风险,逻辑清晰,适合横向整合不同类
扩展:Mixin编程模式
- 概念:混入机制,一种灵活的扩展方式
- 学习建议:查看扩展阅读,搜索Mixin编程机制及例题
二、类对象与实例对象
- 核心结论:类对象、实例对象是不同的对象,类定义后即成为类对象
- 类属性vs实例属性(CC类count属性案例)
- 初始状态:类对象CC.count=0,实例对象a.count/b.count/c.count均为0
- 实例属性赋值:c.count +=10 → c.count=10,a/b的count仍为0(生成实例属性覆盖类属性)
- 类属性赋值:CC.count +=100 → CC.count=100,a/b.count=100,c.count仍为10(实例属性优先)
- 底层逻辑:类属性与类对象绑定,是静态属性;实例属性赋值会生成新属性覆盖类属性
- 重要坑点:属性名与方法名冲突 → 属性会覆盖方法
- 案例:CC类有x()方法,实例c.x=1后,c.x变成整数,无法调用原方法
- 避坑约定
- 类定义"少吃多餐":利用组合/继承扩展,不堆砌所有功能
- 命名区分词性:属性用名词,方法用动词
三、绑定机制:方法与实例的关联
- Python绑定规则:方法需要实例才能被调用
- 反面案例:类中方法无self参数 → 实例调用报错(自动传实例本身,参数不匹配)
- 绑定的核心作用(setXY案例)
- 实例调用dd.setXY(4,5) → 自动传入dd作为self参数
- self.x=4、self.y=5 → 实际是给实例dd添加x、y属性
- 验证方式:__dict__属性查看对象属性 → dd.__dict__有x/y,类对象CC.__dict__无
- 特殊实验:删除类对象后实例仍可调用方法
- 操作:del CC后,实例dd仍能调用printXY()
- 原理:类方法是静态的,程序运行期间内存中保留,仅程序退出时释放
核心建议
- 优先使用实例属性(self.xxx),跟踪实例自身状态
- 类属性仅用于跟踪与类相关的全局值