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

疏老师-python训练营-Day28类的定义和方法

@浙大疏锦行

PS:每天的内容都有示例代码的,在gitee主页 不是只有讲义的几句话,,不会还有人不知道吧

知识点回顾:

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

一.知识点学习

DAY28

之前大家已经接触过类的概念,我们也反复强调了类的实例化。

为了避免有的同学之前没看过复试班的内容或者已经遗忘,我们来简单的复习下

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

现在我们来学一下自己定义一个类,这会让我们对于类这个对象理解的更加深刻

ps:类的操作很多,我们这里只说一些在深度学习领域最常见和通用的

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

  1. 关键字class
  2. 类名
  3. 语法固定符号冒号(:)
  4. 一个初始化函数__init__(self)

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

Pass占位符和缩进

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

许多时候,当规划好准备写一个函数、或者一个类,关键词定义后,会先用pass占位,避免运行错误,等到想好写什么再去补上

比如def、class这些定义的关键词后,必须有一个有占据缩进位置的代码块。

还有下面这些依赖缩进的语句,都可以用pass语句来占位

这个pass就是个占位符,当你这个功能还没想好又不想报错就写个pass,后续加功能比如print('hello'),就把pass删除,写print('hello')就行。

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

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

类的初始化方法

初始化方法又叫构造方法、特殊方法

类有2种方法

  1. 初始化方法,
  2. 普通放大
class Teacher: # 这里不需要括号def __init__(self): #初始化方法,这里没有传入参数self.name = "Susan" # 给类定义一些属性self.subject = "English"self.age = 33Teacher = Teacher() # 创建一个Teacher类的实例
print(Teacher.name) # 输出: Susan

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

针对于类class,可以这么理解:如果老师问一个有35个同学的班级要个人信息表(姓名,性别,年龄等等)如果不做格式要求,老师可能会收到35份格式不同的表(比如顺序不同,排版不同,表格大小不同),现在老师做了一张表格(类,如上文Teacher类)规定格式,每个同学打印表格(实例化或者初始化teacher = Teacher("Susan", 33)),这样表格就有条例,每个同学格式都一样。上述代码teacher = Teacher("Susan", 33),这个teacher它的类型是Teacher类类型。我再写个teacher1,看我下面代码。无论是teacher还是teacher1都是Teacher类类型。

其中,self.xx是用来表明这个属性“归属于”这个类自己的(self)。比如self.name,就代表着:“自己的名字”,self等于“自己”,这个self指向类的实例化地址,传入的self.xx是它的属性。 以后要是用它的属性值,即使是从外界参数传入的,前面也必须加上self.xx,否则传入的参数没价值(例外的情况我们不提)

类的普通方法

除了init方法(初始化方法,又名构造方法),还包含一些普通方法(自己定义)

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

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

特性init 方法普通方法
调用时机创建实例时自动调用手动通过实例调用
是否需要显式调用
默认名称必须是 init自定义
主要用途初始化实例属性实现类的行为逻辑
参数要求第一个参数必须是 self第一个参数必须是 self
返回值必须返回 None(隐式)可以返回任意类型的值

我上述代码有标成员属性和成员方法。一个很容易错的地方是成员方法一般是我们自己定的,比如今天作业有计算面积计算周长,很容易忽视self,成员方法必须有self,否则会报错。以菜刀为例,设定菜刀类,菜刀的大小,重量,材料都是成员属性,成员方法就是砍,切,劈。

类的继承

类已经是比较优秀的封装了,封装了函数、封装了属性

正如装饰器进一步封装了函数的可复用的功能,装饰器函数封装了函数

那么有没有东西可以进一步封装类呢?这就引出了类的继承

在面向对象编程中,继承允许一个类(子类)继承另一个类(父类)的属性和方法,从而实现代码复用和功能扩展。子类可以:

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

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

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

仔细观察下方实例代码的注释,写的非常详细

# 先沿用之前定义的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("微积分")  # 调用子类新增的方法

# super()函数 除了在构造方法中使用,还可以在其他方法中使用# 定义一个父类
class Animal:def __init__(self, name, age):self.name = nameself.age = agedef speak(self):print(f"{self.name} 发出声音")class Dog(Animal):def speak(self):super().speak()  # 先调用父类的方法print("汪汪叫")    # 再添加子类的行为dog = Dog("旺财", 3)
dog.speak() 

所以重写父类的方法,也包含2种

  1. 直接重写:本质是会优先用子类的同名方法,完全替代父类方法,父类逻辑不会执行。
  2. 使用super()重写,保留父类方法的核心逻辑,并在其基础上扩展。

作业

题目1:定义圆(Circle)类

要求:

  1. 包含属性:半径 radius。
  2. 包含方法:
  • calculate_area():计算圆的面积(公式:πr²)。
  • calculate_circumference():计算圆的周长(公式:2πr)。
  1. 初始化时需传入半径,默认值为 1。
# 示例运行
circle = Circle(5)
print(f"半径:{circle.radius}")       # 输出:半径:5
print(f"面积:{circle.calculate_area()}")   # 输出:面积:78.54(保留两位小数)
print(f"周长:{circle.calculate_circumference()}") # 输出:周长:31.42(保留两位小数)

做:

import math
class Circle:def __init__(self,radius):# 成员属性是半径self.radius=radiusdef calculate_area(self):# 这个自定义的普通成员方法一定要加self,否则肯定报错s=math.pi*(self.radius**2)return sdef calculate_circumference(self):l=2*math.pi*self.radiusreturn l# 初始化(激活模型)
circle=Circle(5)# 我们 __init__(self,radius)只有radius一个量(传参忽视self)就传一个量就行
print(f"半径:{circle.radius}")       # 输出:半径:5
print(f"面积:{circle.calculate_area():.2f}")   # 输出:面积:78.54(保留两位小数)
print(f"周长:{circle.calculate_circumference():.2f}") # 输出:周长:31.42(保留两位小数)

题目2:定义长方形(Rectangle)类

  1. 包含属性:长 length、宽 width。
  2. 包含方法:
  • calculate_area():计算面积(公式:长×宽)。
  • calculate_perimeter():计算周长(公式:2×(长+宽))。 is_square() 方法,判断是否为正方形(长 == 宽)。
  1. 初始化时需传入长和宽,默认值均为 1。
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

做:

class Rectangle:def __init__(self,length,width):# 成员属性都这个格式self.width=widthself.length=lengthdef calculate_area(self):# 定义普通成员方法必须有selfs=self.width*self.lengthreturn sdef calculate_perimeter(self):l=2*(self.length+self.width)return ldef is_square(self):if self.length==self.width:b=Trueelse :b=Falsereturn b# 激活模型
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

题目3:图形工厂

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

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

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

shape1 = create_shape("circle", 5)
print(shape1.calculate_circumference())  # 输出:31.42shape2 = create_shape("rectangle", 3, 4)
print(shape2.is_square())                # 输出:False

做:

import math
# 1.矩阵类,里面是执行矩阵类型的操作,示例只要求我们判断是不是正方形,计算面积和周长的我就删了
class Rectangle:def __init__(self,length,width):# 成员属性都这个格式self.width=widthself.length=lengthdef is_square(self):if self.length==self.width:b=Trueelse :b=Falsereturn b# 2.圆类,里面是执行圆类型的操作,示例要求我们计算它的周长,计算面积就删了
class Circle:def __init__(self,radius):# 成员属性是半径self.radius=radiusdef calculate_circumference(self):l=2*math.pi*self.radiusreturn ldef create_shape(shape_type, *args):#根据类型(shape_type)创建不同图形对象:图形工厂(函数或类)if shape_type=="circle":return Circle(args[0])  # 直接使用第一个参数作为半径elif shape_type=="rectangle":return Rectangle(*args)else:print("重输,只有圆和矩阵")shape1 = create_shape("circle", 5)
print(f'{shape1.calculate_circumference():.2f}')  # 输出:31.42
shape2 = create_shape("rectangle", 3, 4)
print(shape2.is_square())
print(f'shape1的类型是{type(shape1)}')
print(f'shape2的类型是{type(shape2)}')

注意事项:

这道题有个注意事项,在上图这个函数中,一定要写return Circle(arg[0]),看一下下图我原来做错的地方。

 我原来的函数只是创立了类对象,却没有return所以报错。所以一定要返回。

http://www.dtcms.com/a/302276.html

相关文章:

  • 【LeetCode 热题 100】35. 搜索插入位置——二分查找(闭区间)
  • 区块链分叉原理与代码仿真
  • leetcode 2044. 统计按位或能得到最大值的子集数目 中等
  • 主要分布于内侧内嗅皮层的层Ⅲ的网格-速度联合细胞(Grid × Speed Conjunctive Cells)对NLP中的深层语义分析的积极影响和启示
  • 热斑漏检率↓78%!陌讯多模态算法在无人机光伏巡检的轻量化实践
  • 问题大全【1】
  • 【深度解析】R语言与作物模型(以DSSAT模型为例)融合应用
  • 散点图(散点矩阵)相关介绍
  • 【计算机科学与应用】基于多域变换的视频水印嵌入算法研究
  • 电脑出现英文字母开不了机怎么办 原因与修复方法
  • 开发笔记 | 实现人物立绘的差分效果
  • 达梦有多少个模式
  • 低成本嵌入式Linux开发方案:通过配置文件实现参数设置
  • LeetCode 68:文本左右对齐
  • 如何解决pip安装报错ModuleNotFoundError: No module named ‘papermill’问题
  • Docker搭建Hadoop集群
  • 进程管理(systemd)
  • 企业微信服务商创建第三方应用配置数据回调url和指令回调url的java代码实现
  • Python系统交互库全解析
  • Entity Framework Core (EF Core) 中Database
  • 归雁思维:解锁自然规律与人类智慧的桥梁
  • Online Proofing System(OPS)在线校样系统使用说明
  • Linux进程概念(五)进程地址空间
  • Leaflet 综合案例 - 路径规划
  • 医疗领域非结构化数据处理技术突破与未来演进
  • svn与git Merge重要区别讲解
  • C# 提取字符串 指定开始和结尾字符
  • 人机交互打字游戏
  • C#高级:通过修改注册表实现系统代理服务器的启用、编辑和禁用
  • 【计算机网络】计算机网络中光猫、交换机、路由器、网关、MAC地址是什么?两台电脑是如何联通的?