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

DAY28-类的定义和方法

知识点回顾:
  1. 类的定义
  2. pass占位语句
  3. 类的初始化方法
  4. 类的普通方法
  5. 类的继承:属性的继承、方法的继承

 (一)类

类是对属性和方法的封装,可以理解为模板,通过对模板实例化可以实现调用这个类的属性和方法。比如创建一个随机森林类,然后就可以调用他的训练和预测方法。

  • 一个常见的类的定义包括:

1. 关键字class

2. 类名

3. 语法固定符号冒号(:)

4. 一个初始化函数__init__(self)  

注意:注意:init左右各有两个下划线__,需要传入self这个特殊的参数。

  •  Pass占位符和缩进
class ClassName: # 类名通常遵循大驼峰命名法 (UpperCamelCase),即每个单词的首字母都大写,class是定义类的关键词# 类的代码块 (可以包含属性定义、方法定义等)pass # pass 是一个占位符,表示这里暂时没有任何内容

总结:

Python 通过缩进来定义代码块的结构。当解释器遇到像 def, class, if, for 这样的语句,并且后面跟着冒号 : 时,它就期望接下来会有一个或多个缩进的语句来构成这个代码块。如果它没有找到任何缩进的语句(即代码块是空的),它就无法确定这个结构的范围,因此会抛出 IndentationError。

pass 语句的存在就是为了解决这个问题:它本身不执行任何操作,但它是一个有效的 Python 语句。所以,当你需要一个语法上存在的代码块,但又暂时不想在其中放入任何实际的逻辑时,pass 就是一个完美的占位符,它告诉解释器:“这里有一个代码块,但它什么也不做。”

  • 类的初始化

代码1

class Teacher: # 这里不需要括号def __init__(self): #__init__为初始化方法,这里没有传入参数,self 是类方法的第一个参数,它代表类的实例本身self.name = "Susan" # 给类定义一些属性self.subject = "English"self.age = 33Teacher = Teacher() # 创建一个Teacher类的实例,并将其赋值给变量 Teacher
print(Teacher.name) # 输出: Susan

代码2

class Teacher:def __init__(self, name, age):# 初始化方法,传入了参数self.name = name # 外界的参数,需要通过self.xxx来复制给类自己的属性self.age = ageself.subject = "English"  # 这个属性仍然是在创建时就设定好的# 创建一个Teacher对象的例子,构造方法的参数必须
teacher = Teacher("Susan", 33) # 如果在初始化方法中设置了非默认的参数,那么外界就必须要传入才行
print(teacher.name)  # 输出: Susan
print(teacher.age)   # 输出: 33
print(teacher.subject)  # 输出: English

两者区别:

1. 初始化方法参数 :代码2的 __init__ 方法接收 name 和 age 两个参数,创建实例时需要传入这两个参数;而代码1的 __init__ 方法不接收参数,实例的属性值在方法内部固定设置。
2. 灵活性 :当前代码创建实例时可以传入不同的 name 和 age 值,每个实例的 name 和 age 可以不同,更加灵活;之前的代码所有实例的 name 、 subject 和 age 都是固定的。

  • 类的普通方法
特性__init__ 方法普通方法
调用时机创建实例时自动调用手动通过实例调用
是否需要显式调用
默认名称必须是 __init__自定义
主要用途初始化实例属性实现类的行为逻辑
参数要求第一个参数必须是 self第一个参数必须是 self
返回值必须返回 None(隐式)可以返回任意类型的值
是否可重载
继承行为子类不定义时会继承父类的 __init__子类不定义时会继承父类的普通方法
访问权限通常用于初始化内部属性(self.xxx可操作实例属性或实现功能
是否支持装饰器是(但通常不用于 __init__是(如 @classmethod@staticmethod
典型示例def __init__(self, name): self.name = namedef show(self): print(self.name)

普通方法和init方法的差别在于,init方法是类的构造方法,当创建对象时,会自动调用init方法----只要你创建这个类对象了,这个init函数就会执行

普通方法是只有你调用类的这个方法的时候,函数才会执行

代码示例:

class Teacher:# 初始化方法接受参数以动态设置教师的属性def __init__(self, name, subject, age):self.name = nameself.subject = subjectself.age = age# 不是init的都叫做普通方法# 普通方法,模拟教师上课的行为def teach_lesson(self):print(f"{self.name}正在教{self.subject}。")# 另一个普通方法,模拟教师批评学生的行为def criticize(self, student_name):print(f"{self.name}正在批评{student_name}。")# 创建Teacher类的实例
teacher = Teacher("Susan", "English", 33)# 调用教师的方法
teacher.teach_lesson()
teacher.criticize("John")#普通方法的参可以等到调用该方法的时候再传
Susan正在教English。
Susan正在批评John。
  • 类的继承

 正如装饰器进一步封装了函数的可复用的功能,装饰器函数封装了函数。那么有没有东西可以进一步封装类呢?这就引出了类的继承。在面向对象编程中,继承允许一个类(子类)继承另一个类(父类)的属性和方法,从而实现代码复用和功能扩展。子类可以:

1. 复用父类的代码(无需重新实现)。

2. 重写父类的方法(修改或增强功能)。

3. 添加新的方法和属性(扩展功能)。

重写父类方法有两种:

1. 直接重写:本质是会优先用子类的同名方法,完全替代父类方法,父类逻辑不会执行。

2. 使用super()重写,保留父类方法的核心逻辑,并在其基础上扩展。

代码示例:

# 先沿用之前定义的teacher类
class Teacher:def __init__(self, name, subject, age):self.name = nameself.subject = subjectself.age = agedef teach_lesson(self):print(f"{self.name}正在教{self.subject}。")def criticize(self, student_name):print(f"{self.name}正在批评{student_name}。")# 继承 Teacher 类,起名特级教师
class MasterTeacher(Teacher): # 1. 继承需要在括号中指定父类def __init__(self, name, subject, age, experience_years):# 2. 继承的时候需要调用父类的构造方法,所以需要传入父类的参数,同时也可以传入自己的参数# 调用父类的构造方法初始化基本属性super().__init__(name, subject, age) # 3. 调用父类的构造方法,这里的super()是一个内置函数,返回父类的实例# 4. 此时子类自动拥有了父类的属性和方法# 添加子类特有的属性self.experience_years = experience_years # 5. 子类特有的属性可以在这里定义# 重写父类方法,增强功能-----如果子类定义了与父类同名的方法,子类实例会优先调用子类的方法。def teach_lesson(self): # 6. 重写父类的方法print(f"{self.name}(特级教师)正在用高级方法教授{self.subject}。")# 新增子类特有的方法def give_lecture(self, topic): print(f"{self.name}正在举办关于{topic}的讲座。")# 创建子类实例
master = MasterTeacher("王教授", "数学", 45, 20)# 调用继承的方法
master.teach_lesson()     # 调用重写的父类的方法
master.criticize("李同学")  # 调用父类的方法,如果不修改方法,则可以直接继承父类的方法# 调用子类特有的方法
master.give_lecture("微积分")  # 调用子类新增的方法

 (二)作业

定义圆(Circle)类

要求:

  1. 包含属性:半径 radius。
  2. 包含方法:
  • calculate_area():计算圆的面积(公式:πr²)。
  • calculate_circumference():计算圆的周长(公式:2πr)。

     3.初始化时需传入半径,默认值为 1。

 

import math
class Circle:def __init__(self,radius = 1):self.radius = radiusdef calculate_area(self):return round(math.pi*self.radius*self.radius)def calculate_circumference(self):return round(2*math.pi*self.radius)
circle = Circle(5)
print(f"半径:{circle.radius}")       # 输出:半径:5
print(f"面积:{circle.calculate_area()}")   # 输出:面积:78.54(保留两位小数)
print(f"周长:{circle.calculate_circumference()}") # 输出:周长:31.42(保留两位小数)

 输出结果:

半径:5
面积:79
周长:31

定义长方形(Rectangle)类

  1. 包含属性:长 length、宽 width。
  2. 包含方法:
  • calculate_area():计算面积(公式:长×宽)。
  • calculate_perimeter():计算周长(公式:2×(长+宽))。 is_square() 方法,判断是否为正方形(长 == 宽)。

    3. 初始化时需传入长和宽,默认值均为 1。

class Rectangle:def __init__(self,length = 1,width = 1):self.length = lengthself.width = widthdef calculate_area(self):return round(self.length * self.width )def calculate_perimeter(self):return 2*(self.length + self.width)def is_square(self):return self.length == self.width
rect = Rectangle(4, 6)
print(f"长:{rect.length}, 宽:{rect.width}")  # 输出:长:4, 宽:6
print(f"面积:{rect.calculate_area()}")      # 输出:面积:24
print(f"周长:{rect.calculate_perimeter()}")  # 输出:周长:20
print(f"是否为正方形:{rect.is_square()}")    # 输出:是否为正方形:Falsesquare = Rectangle(5, 5)
print(f"是否为正方形:{square.is_square()}")  # 输出:是否为正方形:True

输出结果:

长:4, 宽:6
面积:24
周长:20
是否为正方形:False
是否为正方形:True

图形工厂

创建一个工厂函数 create_shape(shape_type, *args),根据类型创建不同图形对象:图形工厂(函数或类)

shape_type="circle":创建圆(参数:半径)。

shape_type="rectangle":创建长方形(参数:长、宽)。

def create_shape(shape_type, *args):if shape_type == "circle":return Circle(*args)elif shape_type == "rectangle":return Rectangle(*args)else:raise ValueError(f"未知图形类型: {shape_type}")shape1 = create_shape("circle", 5)
print(shape1.calculate_circumference())  # 输出:31.42shape2 = create_shape("rectangle", 3, 4)
print(shape2.is_square())                # 输出:False

 输出结果:

31.41592653589793
False

相关文章:

  • 深入解析Spring Boot与Spring Security的集成实践
  • 无线数传模块支持园区多节点电力参数同步监测配置指南
  • Java 注解篇:@RequestMapping
  • 大模型技术演进与应用场景深度解析
  • LVGL- Calendar 日历控件
  • 联想笔记本黑屏了,排线出问题还是静电
  • jvm安全点(三)openjdk17 c++源码垃圾回收之安全点结束,唤醒线程
  • Mysql 8.0.32 union all 创建视图后中文模糊查询失效
  • 数字电子技术基础(五十九)——脉冲触发的触发器
  • (8)python开发经验
  • 开源安全大模型Foundation-Sec-8B实操
  • Vim编辑器命令模式操作指南
  • python打卡day28
  • Florence2代码实战
  • STM32IIC实战-OLED模板
  • 端口443在git bash向github推送时的步骤
  • 手机打电话时由对方DTMF响应切换多级IVR语音应答(二)
  • C++中析构函数不设为virtual导致内存泄漏示例
  • 使用glsl 来做视频矫正
  • 单细胞转录组(2)单细胞测序原理
  • 用贝多芬八首钢琴三重奏纪念风雨并肩20年
  • 试点首发进口消费品检验便利化措施,上海海关与上海商务委发文
  • 美国务卿鲁比奥抵达会场,将参加俄乌会谈
  • 商务部召开全国离境退税工作推进会:提高退税商店覆盖面,扩大入境消费
  • 媒体:“重病老人银行取款身亡”涉事家属称已和解,银行将支付十万
  • 秘鲁总理辞职