Python初学者笔记第二十四期 -- (面向对象编程)
第33节课 面向对象编程
1. 面向对象编程基础
1.1 什么是面向对象编程
面向过程:执行者 耗时 费力 结果也不一定完美
面向对象:指挥者 省时 省力 结果比较完美
面向对象编程(Object-Oriented Programming, OOP)是一种编程范式,它使用"对象"来设计应用程序和软件。在Python中,一切皆为对象。面向对象编程的核心概念包括:类、对象、属性和方法。
面向对象思想就是把复杂的问题变成一个个会 “自己动” 的小模块。
比如你要模拟 “开车去超市” 的场景:
- 汽车是一个 “对象”:它有自己的属性(颜色、油量、速度)和行为(加油、刹车、转向)。
- 你也是一个对象:有属性(名字、年龄)和行为(踩油门、打电话)。
- 超市还是一个对象:有属性(地址、营业时间)和行为(开门、结账)。
**核心思路:**把万物当成 “会干活的小人”
重点:每个对象自己管自己的事,比如汽车自己处理 “加油” 的逻辑,你不用操心它内部怎么喷油 —— 这就是面向对象的核心思维。
如果不用面向对象,就像 “自己动手做所有事”——面向过程思想:
- 比如模拟 “公司考勤系统”,传统方法要写一堆代码处理 “员工打卡”“计算工资”“生成报表”,所有逻辑混在一起,改一个小功能就得重写一大片。
- 用面向对象后:
- 每个员工是一个对象,自己管 “打卡记录”;
- 财务是一个对象,自己算 “工资计算”;
- 报表是一个对象,自己生成 “数据统计”。
哪个模块出问题,直接改对应的对象就行,就像坏了的汽车零件直接换,不用拆整车。
# 面向过程的思想 计算矩形的面积
def 计算矩形面积(长度, 宽度):return 长度 * 宽度
print(计算矩形面积(10,10))# 面向对象的思想
class 矩形:def __init__(self,长度,宽度):self.长度 = 长度self.宽度 = 宽度def 计算面积(self):return self.长度 * self.宽度矩形A = 矩形(10,5)
矩形B = 矩形(100,2)
print(矩形A.计算面积())
print(矩形B.计算面积())
1.2 类和对象
类(Class)是对象的蓝图或原型,定义了对象的属性和行为。对象(Object)是类的实例,代表类定义的具体实体。
- 类 = 蛋糕食谱:
食谱里写着 “需要面粉 200g、鸡蛋 3 个、糖 100g”(这是蛋糕的 “属性”),还写着 “混合材料→烤箱 180 度烤 30 分钟”(这是蛋糕的 “做法”,相当于对象的 “行为”)。
重点:食谱本身不是蛋糕,而是告诉别人 “怎么做出一个蛋糕” 的模板。 - 对象 = 按照食谱烤出来的草莓蛋糕:
你按食谱做出了一个具体的蛋糕,它的颜色是粉色(因为加了草莓酱),重量 500g,还能被吃掉(行为)。
重点:这个蛋糕是 “实实在在存在的物体”,有自己独特的属性(比如别人的蛋糕可能是巧克力味,你的是草莓味)。
维度 | 类(图纸) | 对象(实物) |
---|---|---|
是否真实存在 | 不存在(是抽象的模板) | 存在(是具体的个体) |
数量 | 一个类可以对应多个对象 | 每个对象都是类的一个 “实例” |
属性与行为 | 定义 “应该有什么”(比如手机类定义 “电量”) | 拥有 “具体的属性值”(比如某手机电量 80%) |
作用 | 用于创建对象,减少重复设计 | 用于解决实际问题(比如用手机打电话) |
class Dog:# 类属性 所有对象共享的集体属性 只有一份species = "犬科"# 构造函数 创建对象时自动调用,用于初始化对象的属性# self 区分对象的 看对象的地址 唯一的def __init__(self, name, age, sex="公"):print(f"{name}狗狗,正在成产中...")# 实例属性 成员变量 对象独有属性self.name = nameself.age = ageself.sex = sex# 实例方法 成员函数def bark(self):print(f'{self.name}正在汪汪叫!')# 实例方法 成员函数def get_info(self):print(f'一只名字叫{self.name}的狗,年龄{self.age}岁')def __del__(self):print(f"{self.name}狗狗,正在销户中...")# 创建Dog的对象 实际上引用的是构造函数 -> __init__()
dog1 = Dog("旺财", 3) # 存的是对象的地址 self
dog2 = Dog("狗蛋", 2, sex="母")print(dog1.name, dog1.age) # 实际上是用过地址找对象 从对象空间中找变量
print(dog2.name, dog2.age)print(dog1.species, dog2.species)dog1.bark()
dog1.get_info()
dog2.bark()
dog2.get_info()print(dog1.sex, dog2.sex)dog1.species = "人类"
print(dog1.species)
- 类属性:所有对象共享的 “集体属性”
- 实例属性:每个对象独有的 “个人属性”
- 实例方法:对象能执行的 “个人行为”
类型 | 定义位置 | 归属 | 特点 |
---|---|---|---|
类属性 | 类内部,方法外部 | 类 | 所有对象共享,修改后全局生效 |
实例属性 | 方法内(如__init__ ),用self. 声明 | 对象 | 每个对象独立,修改不影响其他对象 |
实例方法 | 类内部,第一个参数是self | 对象 | 操作对象的实例属性,需通过对象调用 |
1.3 构造函数和析构函数
构造函数(__init__
)在创建对象时自动调用,用于初始化对象的属性。析构函数(__del__
)在对象被销毁时自动调用,用于执行清理操作。
构造函数:对象的 “出生证明办理器”
- 就像 “新生儿出生时,医院会登记姓名、出生日期等信息”:
- 构造函数的作用就是在对象创建时,给对象 “初始化” 必要的属性。
- 没有构造函数,对象就像没有身份信息的 “黑户”,无法正常使用。
一般而言,只有当创建对象时才调用构造函数,对象创建之后,该对象就不应该再去调用构造函数了。
# 不推荐
dog1.__init__("哈哈", 12)
dog1.bark()
dog1.get_info()
析构函数:对象的 “注销手续办理器”
- 就像 “人去世后,需要注销户口、收回身份证”:
- 析构函数的作用是在对象被销毁时,执行清理工作(如释放内存、关闭文件等)。
- 虽然不常用,但在处理资源占用时很重要(如数据库连接、文件句柄)。
类型 | 方法名 | 调用时机 | 核心作用 | 生活类比 |
---|---|---|---|---|
构造函数 | __init__() | 创建对象时自动调用 | 初始化对象属性,分配资源 | 办出生证明、登记身份信息 |
析构函数 | __del__() | 对象被销毁时自动调用 | 释放资源,执行清理工作 | 办注销手续、回收资源 |
def __init__(self, name, age, sex="公"):print(f"{name}狗狗,正在成产中...")# 实例属性 成员变量 对象独有属性self.name = nameself.age = ageself.sex = sexdef __del__(self):print(f"{self.name}狗狗,正在销户中...")
2. 面向对象的三大特性
2.1 封装
封装是将数据和方法捆绑在一起,对外部隐藏对象的内部细节,只暴露必要的接口。在Python中,可以使用下划线前缀来表示属性或方法的访问级别。
- 公有属性:全家都能随便用的 “客厅”
- 受保护属性:只给家人用的 “卧室”
- 私有属性:禁止外人进入的 “保险柜”
属性类型 | 标记方式 | 访问限制 | 生活类比 |
---|---|---|---|
公有属性 | 无前缀 | 类内外均可自由访问、修改 | 客厅(谁都能进) |
受保护属性 | 单下划线_ | 建议类内部使用,外部可访问(靠约定) | 卧室(家人专用,外人少进) |
私有属性 | 双下划线__ | 类外部无法直接访问,需通过方法操作 | 保险柜(只有主人能开) |
# 银行账户类
class BankAccount:def __init__(self, owner, balance=0):self.__owner = ownerself.__balance = balanceself.__password = "123456"# 存钱def deposit(self, amount):if amount > 0:self.__balance += amountprint(f"成功存入{amount}元!,余额{self.__balance}")else:print(f'存钱失败!存入钱数为负数{amount}')# 取钱def withdraw(self, amount):if 0 < amount <= self.__balance:self.__balance -= amountprint(f"成功取得{amount}元,余额{self.__balance}")else:print(f'余额不足或为负数{amount},余额{self.__balance}')# 查询余额def get_balance(self):print(self.__get_info())def __get_info(self):return f"账户名:{self.__owner},余额:{self.__balance}"account = BankAccount("张三", balance=100)
account.deposit(100)
account.deposit(-1000)
account.withdraw(50)
account.withdraw(1000)
account.get_balance()# print(account.owner)
# print(account.__balance)
# 错误操作
# account._balance = -100000000000
# print(account.__balance)
# print(account.__password)
2.2 继承
继承允许一个类(子类)获取另一个类(父类)的属性和方法。这促进了代码重用并建立了类之间的层次关系。
用大白话来讲,继承就像 “子承父业”—— 子类可以直接 “继承” 父类的属性和方法,不用自己重新写一遍,既能减少重复代码,又能体现事物之间的 “所属关系 is - a”。
class Animal:def __init__(self, name, species, color):self.name = nameself.species = speciesself.color = colordef bark(self):print(f"这是动物{self.name}在说话")def eat(self):print(f'动物{self.name}在吃东西')def info(self):return f"{self.name},{self.species},{self.color}"class Dog(Animal):def __init__(self, name, species, color, breed):# 复用父类初始化的过程super().__init__(name, species, color)# 子类的特有属性初始化self.breed = breed# 重写从父类继承而来的函数def bark(self):super().bark()print(f"狗狗{self.name},{self.breed},在汪汪叫")def eat(self):print(f'狗狗{self.name},吃骨头')# 子类特有的行为def lookDoor(self):print("狗狗可以看门啊!")class Cat(Animal):def __init__(self, name, species, color):super().__init__(name, species, color)def bark(self):print(f"猫猫{self.name},{self.color},在喵喵叫")def eat(self):print(f'猫猫{self.name},吃鱼')# 子类特有的行为def zhuoJerry(self):print("猫猫可以捉老鼠")class Pig(Animal):def __init__(self, name, species, color, weight):super().__init__(name, species, color)self.weight = weightdef bark(self):print(f"猪猪{self.name},{self.weight},在哼哼叫")def eat(self):print(f'猪猪{self.name},吃西瓜')# 子类特有的行为def gongBaiCai(self):print("猪猪可以拱白菜")dog = Dog("旺财", "犬科", "黑色", "拉布拉多")
cat = Cat("咪咪", "猫科","鎏金黑")
pig = Pig("佩奇","猪科", "粉色",120)print(dog.info())
print(cat.info())
print(pig.info())
dog.bark()
cat.bark()
pig.bark()
dog.eat()
cat.eat()
pig.eat()
dog.lookDoor()
cat.zhuoJerry()
pig.gongBaiCai()animal = Animal("哈哈","嘻嘻","白色")
animal.bark()
多重继承
Python支持多重继承,一个类可以继承多个父类(最多有一个事物描述性的类Animal 体现is a关系,其他的体现like a 关系,功能的添加)。
class Flyable:def A(self):print("Flyable A")def fly(self):print("可以飞行")class Swimmable:def A(self):print("Swimmable A")def swim(self):print("可以游泳")class Animal:def __init__(self, name, species, color):self.name = nameself.species = speciesself.color = colordef bark(self):print(f"这是动物{self.name}在说话")def eat(self):print(f'动物{self.name}在吃东西')def info(self):return f"{self.name},{self.species},{self.color}"def A(self):print("Animal A")class Pig(Animal, Flyable, Swimmable):def __init__(self, name, species, color, weight):super().__init__(name, species, color)self.weight = weightdef bark(self):print(f"猪猪{self.name},{self.weight},在哼哼叫")def eat(self):print(f'猪猪{self.name},吃西瓜')# 子类特有的行为def gongBaiCai(self):print("猪猪可以拱白菜")def fly(self):print("猪猪在飞")def swim(self):print("猪猪在游泳")pig = Pig("佩奇", "猪科", "粉色", 120)pig.fly()
pig.swim()
pig.A()
print(Pig.__mro__)
当多个父类有相同的方法时,子类调用该方法会优先执行哪个父类的?这就是著名的菱形继承问题:
Python 的 MRO(方法解析顺序):当调用子类的方法时,Python 会按照C3 线性化算法从左到右查找父类。
- 多继承容易导致代码复杂,尽量用单继承或组合模式替代
- 明确 MRO 顺序:用
类名.__mro__
查看方法解析顺序 - 避免方法名冲突:如果多个父类有相同方法名,子类最好重写该方法,明确调用逻辑
组合模式举例
class 人类:def 说话(self):print("我是人类")class 机器:def 充电(self):print("正在充电")class 武器:def 发射导弹(self):print("发射导弹!")class 机甲战士:def __init__(self):self.人类特性 = 人类()self.机器特性 = 机器()self.武器特性 = 武器()def 执行任务(self):self.人类特性.说话()self.机器特性.充电()self.武器特性.发射导弹()高达 = 机甲战士()
高达.执行任务()
2.3 多态
多态是面向对象编程中最神奇的特性之一,就像《变形金刚》里的汽车人 —— 一辆卡车可以变成机器人,一架飞机也可以变成机器人,它们用不同的形态实现相同的「战斗」功能。在编程中,不同类型的对象可以响应同一个方法,但表现出不同的行为,这就是多态。
def animal_eat(animal):# 隐含 只是把它们当成Animal看待 调用的内容仅限于父类的内容或者重写父类的内容animal.eat()if isinstance(animal, Dog): # 把一个Animal当成一个具体的子类来看待 就可以调用子类特有的行为了animal.lookDoor()animal_eat(dog)
animal_eat(cat)
animal_eat(pig)
3. 高级面向对象概念
3.1 抽象类和接口
Python中可以使用abc
模块创建抽象类和接口,强制子类实现特定的方法。
-
抽象类:是一个「不完整的模板」,可以包含一些实现细节,子类需要补充剩余部分(抽象函数)。
- 不能直接实例化,只能作为父类被继承。
- 包含至少一个抽象方法(只有声明,没有实现,用
@abstractmethod
装饰器标记)。 - 可以包含普通方法和属性,子类继承后可以直接使用。
-
接口:是一个「纯粹的契约」,只规定方法签名,不包含任何实现,就像一份「必须遵守的规则清单」。
- 只包含方法签名(没有实现),所有方法默认都是抽象的。
- 不能包含属性,只有方法。
- 一个类可以实现多个接口,就像「签署了多个契约」。
from abc import ABC, abstractmethod
# 包含了抽象函数的类 > 抽象类 不能直接创建对象
class Animal(ABC):def __init__(self, name, species, color):self.name = nameself.species = speciesself.color = color# 抽象函数:只保留函数声明 不保留函数体 抽象函数必须要被子类实现@abstractmethoddef bark(self):pass@abstractmethoddef eat(self):passdef info(self):return f"{self.name},{self.species},{self.color}"# 接口:只有抽象函数的抽象类
class Flyable(ABC):@abstractmethoddef fly(self):passclass Swimmable(ABC):@abstractmethoddef swim(self):passclass Dog(Animal):def __init__(self, name, species, color, breed):# 复用父类初始化的过程super().__init__(name, species, color)# 子类的特有属性初始化self.breed = breed# 重写从父类继承而来的函数def bark(self):super().bark()print(f"狗狗{self.name},{self.breed},在汪汪叫")def eat(self):print(f'狗狗{self.name},吃骨头')# 子类特有的行为def lookDoor(self):print("狗狗可以看门啊!")class Cat(Animal):def __init__(self, name, species, color):super().__init__(name, species, color)def bark(self):print(f"猫猫{self.name},{self.color},在喵喵叫")def eat(self):print(f'猫猫{self.name},吃鱼')# 子类特有的行为def zhuoJerry(self):print("猫猫可以捉老鼠")class Pig(Animal,Flyable, Swimmable):def __init__(self, name, species, color, weight):super().__init__(name, species, color)self.weight = weightdef bark(self):print(f"猪猪{self.name},{self.weight},在哼哼叫")def eat(self):print(f'猪猪{self.name},吃西瓜')# 子类特有的行为def gongBaiCai(self):print("猪猪可以拱白菜")def fly(self):print("猪猪可以飞")def swim(self):print("猪猪可以游泳")dog = Dog("旺财", "犬科", "黑色", "拉布拉多")
cat = Cat("咪咪", "猫科","鎏金黑")
pig = Pig("佩奇","猪科", "粉色",120)# 抽象类不能直接创建对象 本身就不具体
# a = Animal("嘻嘻","haha","123")def animal_eat(animal):# 隐含 只是把它们当成Animal看待 调用的内容仅限于父类的内容或者重写父类的内容animal.eat()if isinstance(animal, Dog): # 把一个Animal当成一个具体的子类来看待 就可以调用子类特有的行为了animal.lookDoor()animal_eat(dog)
animal_eat(cat)
animal_eat(pig)
到底什么是多继承:
(1)只有一个关系表示is a 要么继承一个描述性质的类/抽象类
(2)可以有多个关系表示参 can do ,实现多个接口而已 Flyable,Swimmable,就是给类后期添加额外的功能。拉布拉多天生是否可以导盲?黑背是否天生缉毒?
特性 | 抽象类 | 接口 |
---|---|---|
能否实例化 | 不能 | 不能 |
方法实现 | 可以包含普通方法和抽象方法 | 只能包含抽象方法(默认全是抽象) |
属性 | 可以包含属性 | 不能包含属性 |
继承 / 实现方式 | 单继承(一个子类只能继承一个抽象类) | 多实现(一个类可以实现多个接口) |
设计目的 | 定义「是什么」(is-a 关系) | 定义「能做什么」(can-do 关系) |
3.2 类方法和静态方法
Python中有三种类型的方法:实例方法、类方法和静态方法。
类方法和静态方法是面向对象编程中两种特殊的方法,它们与类的关系就像「家族顾问」和「家族工具」:
-
类方法:绑定到类,能访问和修改类的属性,就像家族中负责管理族谱的顾问。
- 用
@classmethod
装饰器声明,第一个参数必须是cls
(代表类本身)。 - 可以访问和修改类属性,也可以调用其他类方法,但不能直接访问实例属性。
- 通过类名或实例名都能调用。
- 类方法就像「家族会议」,参会者是家族成员(实例),但讨论的是家族共同事务(类属性)。
- 用
-
静态方法:独立于类,不能访问或修改类的属性,就像家族共用的锤子,谁都能用但不隶属于任何人。
- 用
@staticmethod
装饰器声明,没有类似self
或cls
的特殊参数。 - 不能访问或修改类属性和实例属性,完全独立于类的状态。
- 通过类名或实例名都能调用。
- 静态方法就像「计算器」,可以被家族成员(实例)使用,但不记录任何家族信息。
- 用
def is_even(num):return num % 2 == 0print(is_even(10))class MathUtils:# 类属性pi = 3.14# 构造函数 创建对象时调用def __init__(self, value):# 实例属性 只能对象调用self.value = value# 实例方法 只能对象调用def add(self,x):return self.value + x# 类方法 和对象没关系了@classmethoddef get_pi(cls):return cls.pi@classmethoddef set_pi(cls, new_pi):cls.pi = new_pi# 静态方法 和类 对象 都没关系@staticmethoddef is_even(num):return num % 2 == 0
# 调用静态方法
print(MathUtils.is_even(10))math = MathUtils(10)
# 调用实例方法
print(math.add(5))
# 报错 通过类调用实例方法
# print(MathUtils.add(5))
# 对象可以访问类的内容
print(math.pi)
print(math.get_pi())# 通过类去调用类方法/属性
print(MathUtils.pi)
print(MathUtils.get_pi())# 对象也可以调用静态方法
print(math.is_even(10))
print(MathUtils.is_even(10))
生命周期从大到小分别为:静态 -> 类 -> 对象
小可以调大,大不能调小
如果当我们的类不需要创建对象时,而且还要调用其内容的话,可以考虑使用类方法/静态方法
特性 | 类方法 | 静态方法 |
---|---|---|
装饰器 | @classmethod | @staticmethod |
第一个参数 | cls (代表类本身) | 无特殊参数 |
能否访问类属性 | 能 | 不能 |
能否访问实例属性 | 不能 | 不能 |
设计目的 | 操作类状态(如类属性) | 封装与类相关的通用功能(模块) |
3.3 属性装饰器
使用@property
装饰器可以将方法转换为属性,实现更好的封装。
属性装饰器(@property
)是 Python 中一种优雅的语法糖,它能让方法像属性一样被访问,同时保留方法的计算逻辑或验证功能。简单来说,它把一个「函数调用」伪装成「属性访问」,让代码更简洁、更符合直觉。
# 银行账户类
class BankAccount:def __init__(self, owner, balance=0):self.__owner = ownerself.__balance = balanceself.__password = "123456"# Getter 仅用于获取实例属性的值# def get_owner(self):# return self.__owner@propertydef owner(self):return self.__owner@propertydef balance(self):return self.__balance# Setter 用于给实例属性进行赋值# def set_balance(self, amount):# if amount > 0:# self.__balance = amount@balance.setterdef balance(self, value):if value > 0:self.__balance = valueaccount = BankAccount("张三", balance=100)
print(account.get_owner())
print(account.owner)
print(account.balance)
account.set_balance(500)
print(account.balance)
account.set_balance(-500)
print(account.balance)
account.balance = 100000
print(account.balance)
account.balance = -10000000
print(account.balance)
4.魔法函数
魔法函数(Magic Methods)是 Python 中一类特殊的方法,它们的名字以双下划线开头和结尾(如__init__
、__str__
)。这些方法不由开发者直接调用,而是在特定场景下被 Python 解释器自动触发,就像给类赋予了「隐藏超能力」。
通过实现魔法函数,你可以让自定义类支持 Python 的内置语法,例如:
- 使用
len(obj)
获取对象长度 → 实现__len__
- 使用
str(obj)
转换为字符串 → 实现__str__
- 使用
obj1 + obj2
进行加法运算 → 实现__add__
- 使用
for item in obj
进行迭代 → 实现__iter__
常见的魔法函数可分为以下几类:
- 创建与销毁:
__init__
,__del__
- 字符串表示:
__str__
,__repr__
,__format__
- 容器操作:
__len__
,__getitem__
,__setitem__
,__contains__
- 比较运算:
__eq__
,__lt__
,__gt__
,__hash__
- 运算符重载:
__add__
,__sub__
,__mul__
,__div__
- 上下文管理:
__enter__
,__exit__
- 可调用对象:
__call__
对象转字符串
class Point:def __init__(self,x,y):self.x = xself.y = ydef __str__(self):return f"({self.x},{self.y})"p = Point(1,2)
# <__main__.Point object at 0x0000027EC14B1E80>
print(p) # 直接打印对象时 则调用__str__的返回结果
实现自定义列表
通过实现__len__
和__getitem__
,让类可以像列表一样被索引和遍历。
class 成绩册:def __init__(self):self.成绩 = []def 添加成绩(self,分数):self.成绩.append(分数)def __len__(self):return len(self.成绩)def __getitem__(self, 索引):return self.成绩[索引]
socres = 成绩册()
socres.添加成绩(85)
socres.添加成绩(90)
print(len(socres))
print(socres[0])
for socre in socres:print(socre)
实现自定义字典
通过__getitem__
、__setitem__
和__contains__
实现字典功能。
class Config:def __init__(self):self.data = dict()def __getitem__(self, key):return self.data[key]def __setitem__(self, key, value):self.data[key] = valuedef __contains__(self, key):return key in self.datac = Config()
c['地址'] = "127.0.0.1"
c['端口'] = 8080
print(c['地址'])
print(c['端口'])
数值运算
实现__add__
、__sub__
等魔法函数,使对象支持加减乘除。
class Point:def __init__(self,x,y):self.x = xself.y = ydef __str__(self):return f"({self.x},{self.y})"# 定义两个对象相加时的逻辑def __add__(self, other):return Point( self.x + other.x, self.y + other.y)p1 = Point(1,2)
p2 = Point(3,4)
# <__main__.Point object at 0x0000027EC14B1E80>
print(p1) # 直接打印对象时 则调用__str__的返回结果
print(p2)
print(p1 + p2)
比较运算
实现__eq__
、__lt__
等魔法函数,使对象支持比较操作。
class FenShu:def __init__(self, fenzi,fenmu):self.fenzi = fenziself.fenmu = fenmudef __eq__(self, other):return self.fenzi == other.fenzi and self.fenmu == other.fenmudef __lt__(self, other):return self.fenzi / self.fenmu < other.fenzi / other.fenmuf1 = FenShu(1,2)
f2 = FenShu(1,2)
# 此时的 == 默认比地址 除非重写__eq__
print(f1 == f2)
f3 = FenShu(2,5)
print(f3 < f1)
print(f3 > f1)
print(f3 == f1)
_(self):
return f"({self.x},{self.y})"
# 定义两个对象相加时的逻辑
def add(self, other):
return Point( self.x + other.x, self.y + other.y)
p1 = Point(1,2)
p2 = Point(3,4)
<main.Point object at 0x0000027EC14B1E80>
print(p1) # 直接打印对象时 则调用__str__的返回结果
print(p2)
print(p1 + p2)
**比较运算**实现`__eq__`、`__lt__`等魔法函数,使对象支持比较操作。```python
class FenShu:def __init__(self, fenzi,fenmu):self.fenzi = fenziself.fenmu = fenmudef __eq__(self, other):return self.fenzi == other.fenzi and self.fenmu == other.fenmudef __lt__(self, other):return self.fenzi / self.fenmu < other.fenzi / other.fenmuf1 = FenShu(1,2)
f2 = FenShu(1,2)
# 此时的 == 默认比地址 除非重写__eq__
print(f1 == f2)
f3 = FenShu(2,5)
print(f3 < f1)
print(f3 > f1)
print(f3 == f1)