当前位置: 首页 > news >正文

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 继承

image-20250615170516029

继承允许一个类(子类)获取另一个类(父类)的属性和方法。这促进了代码重用并建立了类之间的层次关系。

用大白话来讲,继承就像 “子承父业”—— 子类可以直接 “继承” 父类的属性和方法,不用自己重新写一遍,既能减少重复代码,又能体现事物之间的 “所属关系 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装饰器声明,没有类似selfcls的特殊参数。
    • 不能访问或修改类属性和实例属性,完全独立于类的状态。
    • 通过类名或实例名都能调用。
    • 静态方法就像「计算器」,可以被家族成员(实例)使用,但不记录任何家族信息。
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)
http://www.xdnf.cn/news/1287667.html

相关文章:

  • 计算机网络1-7:第一章 概述 章节小结
  • 用 Apache Iceberg 与 Apache Spark 在 Google Cloud 打造高性能、可扩展的数据湖仓
  • 【Java Web 快速入门】九、事务管理
  • 【论文阅读】RestorerID: Towards Tuning-Free Face Restoration with ID Preservation
  • 【游戏优化笔记】开发中如何减少建筑和树木等环境元素的资源消耗?
  • 【跨服务器的数据自动化下载--安装公钥,免密下载】
  • 【CSS3】录音中。。。
  • 【oracle闪回查询】记录字段短时间被修改的记录
  • 【AI绘画】Stable Diffusion webUI 常用功能使用技巧
  • css之再谈浮动定位float(深入理解篇)
  • react+vite来优化下每次使用hook函数都要引入的情况
  • React (react-amap)高德地图使用(加标记、缩放、缩略图)
  • 荣耀手机无法连接win11电脑,错误消息:“无法在此设备上加载驱动程序 (hn_usbccgpfilter.sys)。”解决方案
  • OBOO鸥柏丨智能会议平板教学查询一体机交互式触摸终端招标投标核心标底参数要求
  • SQL Server增加对UTF-8的支持
  • Baumer高防护相机如何通过YoloV8深度学习模型实现纸箱的实时检测计数(C#代码UI界面版)
  • 谷歌ADK接入文件操作MCP
  • 力扣47:全排列Ⅱ
  • 基于Python的《红楼梦》文本分析与机器学习应用
  • 力扣 hot100 Day71
  • vivo Pulsar 万亿级消息处理实践(2)-从0到1建设 Pulsar 指标监控链路
  • [激光原理与应用-254]:理论 - 几何光学 - 自动对焦的原理
  • 数据结构:中缀到后缀的转换(Infix to Postfix Conversion)
  • Flutter GridView的基本使用
  • Java 工厂方法模式
  • 【项目设计】高并发内存池
  • 北京-4年功能测试2年空窗-报培训班学测开-第七十四天-线下面试-聊的很满意但可能有风险-等信吧
  • cuda排序算法--双调排序(Bitonic_Sort)
  • web前端第二次作业
  • 开发避坑指南(23):Tomcat高版本URL特殊字符限制问题解决方案(RFC 7230 RFC 3986)