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

Python训练营打卡 Day28

类的定义和方法

知识点回顾:

  1. 类的定义:菜谱的模板

    类就像是餐厅的菜谱,它定义了如何制作一道菜的步骤和所需食材。

类是对属性和方法的封装,可以理解为模板,通过对模板实例化可以实现调用这个类的属性和方法。比如创建一个随机森林类,然后就可以调用他的训练和预测方法。现在我们来学一下自己定义一个类,这会让我们对于类这个对象理解的更加深刻

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

class ClassicDish:# 类定义pass

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

  • 关键字 class:就像告诉厨师要开始定义一个菜谱。

  • 类名 ClassicDish:类似于菜谱的名字,比如“宫保鸡丁”,遵循大驼峰命名法。

  • 冒号 ::表示开始定义类的内容。

  • pass:占位语句,表示类目前没有具体内容。

  • 一个初始化函数__init__(self)  

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

pass占位语句:预留一个菜谱位置

假设你是一个餐厅的厨师,你正在编写一个新菜谱。你已经想好了要添加一个新的菜品,但目前还没有具体的烹饪步骤。为了确保这个菜品在菜单上有一个位置,你可以先创建一个“占位符”菜谱。

# 定义一个类,但暂时没有具体内容
class NewSpecialDish:pass  # 这里是一个占位符,表示这个类目前没有具体的功能# 创建一个实例
dish = NewSpecialDish()# 打印实例类型
print(type(dish))  # 输出: <class '__main__.NewSpecialDish'>
  • 类名 NewSpecialDish:就像是新菜谱的名字,为未来的新菜品预留了位置。

  • pass 语句:就像是在菜谱中写了一个占位符,告诉其他厨师“这里有一个新菜品,但我们还没准备好具体的烹饪步骤”。

为什么需要 pass

  1. 预留位置:使用 pass 可以确保类的名称在当前代码中占有一席之地,即使类还没有具体的功能。

  2. 避免错误:Python 需要一个缩进的代码块来定义类或函数,如果没有缩进的代码块,会抛出 IndentationErrorpass 语句可以避免这种错误。

  3. 后续开发:在后续开发中,你可以回来填充这个类的具体内容,而不必担心代码结构的问题。

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

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

类的初始化方法:准备食材

初始化方法就像厨师在烹饪之前准备好所有需要的食材。

class ClassicDish:def __init__(self, main_ingredient, spice_level):self.main_ingredient = main_ingredient  # 主食材self.spice_level = spice_level  # 辣度def prepare_ingredients(self):print(f"准备 {self.main_ingredient},辣度设为 {self.spice_level}")dish = ClassicDish("鸡丁", "中辣")
dish.prepare_ingredients()

  

  • __init__ 方法:就像厨师在开始烹饪前的准备工作,创建对象时自动调用。

  • self 参数:代表当前正在处理的“这道菜”。

  • main_ingredientspice_level:是类的属性,就像菜谱中需要的主食材和辣度等级。

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

        类有2种方法
        1. 初始化方法,

初始化方法可以理解为“准备食材”的过程。

class ClassicDish:def __init__(self, main_ingredient, spice_level):self.main_ingredient = main_ingredient  # 主食材self.spice_level = spice_level  # 辣度def prepare_ingredients(self):print(f"准备 {self.main_ingredient},辣度设为 {self.spice_level}")
  • 初始化方法 __init__:就像厨师在开始烹饪前的准备工作。当你点了一道菜(创建对象),厨师会先准备好所有的食材(初始化属性)。

  • self 参数:代表当前正在处理的“这道菜”。

  • main_ingredientspice_level:是类的属性,就像菜谱中需要的主食材和辣度等级。

  • 调用时:

    dish = ClassicDish("鸡丁", "中辣")
    dish.prepare_ingredients()
    # 输出:准备 鸡丁,辣度设为 中辣

        2. 普通放大

类的普通方法:烹饪步骤

普通方法就像菜谱中的具体烹饪步骤,只有在厨师执行这些步骤时才会进行实际的操作。   

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

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

class ClassicDish:def __init__(self, main_ingredient, spice_level):self.main_ingredient = main_ingredientself.spice_level = spice_leveldef cook(self):print(f"正在烹饪 {self.main_ingredient},辣度 {self.spice_level}")def serve(self):print(f"{self.main_ingredient} 已经做好,可以端上桌了")dish = ClassicDish("鸡丁", "中辣")
dish.cook()   # 输出:正在烹饪 鸡丁,辣度 中辣
dish.serve()  # 输出:鸡丁 已经做好,可以端上桌了
  • cookserve 方法:是普通方法,只有在调用时才会执行。

类的继承-属性的继承、方法的继承:改良菜谱

继承就像在原有菜谱的基础上进行改良,保留原有的步骤,同时添加新的步骤或修改某些步骤。

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

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

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

class SpecialDish(ClassicDish):def __init__(self, main_ingredient, spice_level, special_topping):super().__init__(main_ingredient, spice_level)self.special_topping = special_topping  # 新增的特殊配料def add_special_topping(self):print(f"添加特殊配料:{self.special_topping}")def cook(self):super().cook()self.add_special_topping()special_dish = SpecialDish("鸡丁", "微辣", "腰果")
special_dish.cook()
special_dish.serve()
  • SpecialDish:继承自 ClassicDish 类,保留了原有的属性和方法,同时添加了新的属性和方法。

  • super() 函数:用于调用父类的构造方法,确保父类的初始化逻辑被执行。

  • add_special_topping 方法:是新增的方法,用于添加特殊配料。

  • 重写 cook 方法:在原有 cook 方法的基础上增加了新的步骤。

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

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

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

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

作业

题目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 mathclass Circle:def __init__(self, radius=1):self.radius = radiusdef calculate_area(self):try:if self.radius < 0:return 0return math.pi * self.radius ** 2except TypeError:return 0def calculate_circumference(self):try:if self.radius < 0:return 0return 2 * math.pi * self.radiusexcept TypeError:return 0# 示例运行
circle = Circle(5)
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=1, width=1):self.length = lengthself.width = widthdef calculate_area(self):try:if self.length < 0 or self.width < 0:return 0return self.length * self.widthexcept TypeError:return 0def calculate_perimeter(self):try:if self.length < 0 or self.width < 0:return 0return 2 * (self.length + self.width)except TypeError:return 0def 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

题目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 mathclass Circle:def __init__(self, radius=1):self.radius = radiusdef calculate_area(self):try:if self.radius < 0:return 0return math.pi * self.radius ** 2except TypeError:return 0def calculate_circumference(self):try:if self.radius < 0:return 0return 2 * math.pi * self.radiusexcept TypeError:return 0class Rectangle:def __init__(self, length=1, width=1):self.length = lengthself.width = widthdef calculate_area(self):try:if self.length < 0 or self.width < 0:return 0return self.length * self.widthexcept TypeError:return 0def calculate_perimeter(self):try:if self.length < 0 or self.width < 0:return 0return 2 * (self.length + self.width)except TypeError:return 0def is_square(self):return self.length == self.widthdef create_shape(shape_type, *args):if shape_type == "circle":if len(args) == 1:return Circle(args[0])else:raise ValueError("Circle requires exactly one argument: radius")elif shape_type == "rectangle":if len(args) == 2:return Rectangle(args[0], args[1])else:raise ValueError("Rectangle requires exactly two arguments: length and width")else:raise ValueError("Unsupported shape type")# 测试
shape1 = create_shape("circle", 5)
print(shape1.calculate_circumference())  # 输出:31.41592653589793shape2 = create_shape("rectangle", 3, 4)
print(shape2.is_square())  # 输出:False

@浙大疏锦行

相关文章:

  • 一二维前缀和与差分
  • 十二、Hive 函数
  • 文件转Markdown工具有哪些
  • JavaScript入门【3】面向对象
  • 【第一篇】 创建SpringBoot工程的四种方式
  • 【以及好久没上号的闲聊】Unity记录8.1-地图-重构与优化
  • 当硅基存在成为人性延伸的注脚:论情感科技重构社会联结的可能性
  • JVM 机制
  • 【论文阅读】人脸修复(face restoration ) 不同先验代表算法整理
  • Adobe Illustrator学习备忘
  • 单细胞转录组(4)Cell Ranger
  • 项目管理学习-CSPM-4考试总结
  • vscode用python开发maya联动调试设置
  • Redis 数据类型与操作完全指南
  • 开源语音-文本基础模型和全双工语音对话框架 Moshi 介绍
  • 【Redis】List 列表
  • 谈谈未来iOS越狱或巨魔是否会消失
  • Redis的Hot Key自动发现与处理方案?Redis大Key(Big Key)的优化策略?Redis内存碎片率高的原因及解决方案?
  • 计算机网络(1)——概述
  • Redis——缓存雪崩、击穿、穿透
  • 音乐节困于流量
  • 中国青年报:为见义勇为者安排补考,体现了教育的本质目标
  • 李强:把做强国内大循环作为推动经济行稳致远的战略之举
  • 基金经理调仓引发大金融板块拉升?公募新规落地究竟利好哪些板块
  • 新能源汽车,告别混乱创新
  • 美国和沙特签署上千亿美元军售协议