朔州市网站建设_网站建设公司_Photoshop_seo优化
2025/12/24 8:46:01 网站建设 项目流程

📋 前言

各位伙伴们,大家好!Day 28 是我们编程思维的一次重大升级。在此之前,我们更多的是在编写指令的“脚本”。从今天起,我们将学习成为一名“设计师”,开始构建拥有属性和行为的“对象”。我们将深入探索 Python 面向对象编程 (OOP) 的核心——类 (Class)

可以把想象成一张“饼干模具”,它定义了饼干的形状和配方。而通过这个模具压出来的每一块具体的饼干,就是对象 (Object)实例 (Instance)

今天,我们将从零开始,学习如何设计我们自己的“模具”:

  • 如何定义一个类,以及pass的妙用。
  • 什么是__init__方法?(给饼干注入灵魂)
  • 如何为类添加功能?(教会饼干“跳舞”)
  • 什么是继承?(在“圆形模具”基础上,创造一个“花边圆形模具”)

让我们一起进入对象的奇妙世界,体验创造的乐趣!


一、类的蓝图:定义与初始化__init__

1.1 最简单的类与pass

一个类最基本的结构是class关键字后跟类名。如果暂时不想写任何内容,可以使用pass作为占位符,避免程序因缺少代码块而报错。

# 定义一个“狗”的类,但还没想好它有什么具体功能classDog:pass# pass 告诉 Python:“我知道这里需要代码,但先跳过。”# 我们可以创建这个类的实例,尽管它什么也做不了my_dog=Dog()print(my_dog)# 输出: <__main__.Dog object at 0x...>

1.2 初始化方法__init__:对象的诞生时刻

__init__是一个非常特殊的“魔法方法”,也叫构造方法。当一个对象被创建时(例如my_dog = Dog()),__init__方法会自动被调用。它的主要任务是设置这个新对象的初始状态,也就是它的属性 (Attributes)

  • self:是__init__方法的第一个参数,它代表实例本身。当你创建一个my_dog对象时,self就指向my_dog。通过self.属性名 = 值的方式,我们将属性“绑定”到这个实例上。
classDog:# 当一只狗“诞生”时,我们需要知道它的名字和年龄def__init__(self,name,age):print(f"一只名叫{name}的小狗诞生了!")# 使用 self 将传入的参数绑定为实例的属性self.name=name self.age=age# 创建实例时,必须提供 __init__ 方法需要的参数(除了 self)dog1=Dog("旺财",3)dog2=Dog("大黄",5)# 访问实例的属性print(f"{dog1.name}今年{dog1.age}岁了。")# 输出: 旺财 今年 3 岁了。print(f"{dog2.name}今年{dog2.age}岁了。")# 输出: 大黄 今年 5 岁了。

二、赋予蓝图生命:类的普通方法

如果说属性是对象“是什么”(名词),那么方法 (Methods)就是对象“能做什么”(动词)。

普通方法是定义在类中、以self为第一个参数的函数。它必须通过实例来调用,并且可以访问和操作该实例的属性。

__init__方法 vs 普通方法(来自课程的精炼总结)

特性__init__方法普通方法
调用时机创建实例时自动调用手动通过实例调用
是否需要显式调用
默认名称必须是__init__自定义
主要用途初始化实例属性实现类的行为逻辑
参数要求第一个参数必须是self第一个参数必须是self
返回值必须返回None(隐式)可以返回任意类型的值
classDog:def__init__(self,name):self.name=name# 定义一个“叫”的方法defbark(self):print(f"{self.name}正在汪汪叫!")# 定义一个带参数的“追逐”方法defchase(self,target):print(f"{self.name}正在追逐{target}!")my_dog=Dog("旺财")# 手动调用实例的方法my_dog.bark()my_dog.chase("一只猫")

三、站在巨人的肩膀上:类的继承

继承是 OOP 的三大支柱之一。它允许我们创建一个新类(子类),这个新类可以继承一个已存在类(父类)的所有属性和方法。

这样做的好处是:

  • 代码复用:不用重写父类已有的功能。
  • 功能扩展:可以在子类中添加新功能。
  • 功能重写:可以修改父类的方法以适应子类的特殊需求。

super()的妙用

在子类的__init__方法中,我们通常需要调用super().__init__(...)super()函数会返回父类的实例,调用它的__init__方法可以帮助我们完成父类部分的初始化工作,避免重复代码。

# 定义父类:警犬classPoliceDog(Dog):# 在括号中指定父类def__init__(self,name,department):# 1. 调用父类的 __init__ 来设置 name 属性super().__init__(name)# 2. 添加子类特有的属性self.department=department# 3. 添加子类特有的方法deftrack_trace(self):print(f"来自{self.department}的警犬{self.name}正在追踪线索。")# 4. 重写父类的方法defbark(self):# 可以在重写时,通过 super() 调用父类的原始方法super().bark()print(f"{self.name}的叫声充满了威严!")# 创建子类实例k9_dog=PoliceDog("雷神","缉毒组")# 调用继承自父类的方法k9_dog.chase("嫌疑人")# 调用子类新增的方法k9_dog.track_trace()# 调用被子类重写的方法k9_dog.bark()

四、作业实战:构建你的几何图形库

现在,让我们用今天学到的知识,来创建我们自己的几何图形类库吧!

题目一:定义圆 (Circle) 类

importmathclassCircle:"""定义一个圆类"""def__init__(self,radius=1):"""初始化方法,接收半径,默认为1"""self.radius=radiusdefcalculate_area(self):"""计算并返回圆的面积"""returnmath.pi*self.radius**2defcalculate_circumference(self):"""计算并返回圆的周长"""return2*math.pi*self.radius# --- 示例运行 ---circle=Circle(5)print(f"半径:{circle.radius}")# 输出: 半径: 5print(f"面积:{circle.calculate_area():.2f}")# 输出: 面积: 78.54print(f"周长:{circle.calculate_circumference():.2f}")# 输出: 周长: 31.42

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

classRectangle:"""定义一个长方形类"""def__init__(self,length=1,width=1):"""初始化方法,接收长和宽,默认为1"""self.length=length self.width=widthdefcalculate_area(self):"""计算并返回面积"""returnself.length*self.widthdefcalculate_perimeter(self):"""计算并返回周长"""return2*(self.length+self.width)defis_square(self):"""判断是否为正方形,返回布尔值"""returnself.length==self.width# --- 示例运行 (长方形) ---rect=Rectangle(4,6)print(f"长:{rect.length}, 宽:{rect.width}")# 输出: 长: 4, 宽: 6print(f"面积:{rect.calculate_area()}")# 输出: 面积: 24print(f"周长:{rect.calculate_perimeter()}")# 输出: 周长: 20print(f"是否为正方形:{rect.is_square()}")# 输出: 是否为正方形: False# --- 示例运行 (正方形) ---square=Rectangle(5,5)print(f"\n是否为正方形:{square.is_square()}")# 输出: 是否为正方形: True

题目三:图形工厂 (Shape Factory) 函数

这个题目是点睛之笔!它展示了如何动态地使用我们创建的类。

defcreate_shape(shape_type,*args):""" 一个工厂函数,根据给定的类型和参数创建图形对象。 :param shape_type: 字符串, "circle" 或 "rectangle" :param args: 创建对象所需的参数 (半径, 或 长和宽) :return: 对应的图形对象, 或 None (如果类型不支持) """ifshape_type.lower()=="circle":# 如果是圆形,用 args 创建 Circle 实例# *args 会将元组解包,例如 (5,) -> 5returnCircle(*args)elifshape_type.lower()=="rectangle":# 如果是矩形,用 args 创建 Rectangle 实例# *args 会将元组解包,例如 (3, 4) -> 3, 4returnRectangle(*args)else:# 如果类型未知,打印错误信息并返回 Noneprint(f"错误: 不支持的图形类型 '{shape_type}'")returnNone# --- 示例运行 ---# 创建一个圆形shape1=create_shape("circle",5)ifshape1:print(f"创建的圆形周长是:{shape1.calculate_circumference():.2f}")# 输出: 31.42# 创建一个矩形shape2=create_shape("rectangle",3,4)ifshape2:print(f"创建的矩形是否为正方形:{shape2.is_square()}")# 输出: False# 尝试创建一个不支持的图形shape3=create_shape("triangle",10)

输出:

创建的圆形周长是: 31.42 创建的矩形是否为正方形: False 错误: 不支持的图形类型 'triangle'

五、总结与心得

Day 28 的学习是编程思维的一次质变,我最大的感受有三点:

  1. 封装的力量 (Encapsulation):我不再需要到处写计算圆面积的公式。我把半径 (self.radius) 和计算面积的方法 (calculate_area)封装Circle类里。使用者只需要知道如何创建一个Circle对象并调用它的方法,而无需关心内部实现细节。这让代码更安全、更易用。

  2. 抽象与蓝图 (Abstraction)class Circle本身不是任何一个具体的圆,它是对所有“圆”这一概念的抽象。它定义了作为一个圆必须有什么(半径),能做什么(计算面积和周长)。这种“先设计蓝图,再创造实例”的思想,是解决复杂问题的基础。

  3. 组合与创造 (Composition & Factory):“图形工厂”这个作业太妙了!它让我明白,类本身就是一种强大的“零件”。我们可以像搭积木一样,用一个更高层次的逻辑(工厂函数)来动态地组合和创造这些零件,构建出更灵活、更强大的系统。

从今天起,我看待代码的眼光不再仅仅是“一步步的指令”,而是“一个个相互协作的对象”。这为理解未来复杂的机器学习库(它们都是用类构建的)打下了坚实的基础。

再次感谢 @浙大疏锦行 老师的精彩课程和巧妙的作业设计!

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询