欢迎光临
我们一直在努力

Day 14:【99天精通Python】面向对象编程(OOP)上篇 - 类与对象

Day 14:【99天精通Python】面向对象编程(OOP)上篇 – 类与对象

前言

欢迎来到第14天!

从今天开始,我们将进入Python编程的一个全新阶段——面向对象编程 (Object-Oriented Programming, OOP)。

在之前的课程中,我们主要使用的是面向过程的写法:定义一堆变量,写一堆函数来处理这些变量。这种方式对于简单的脚本很有效,但当项目变大(比如开发一个游戏、一个复杂的网站)时,代码会变得杂乱无章。

OOP 是一种更接近人类思维的编程范式。我们不再只关注"怎么做",而是关注"谁来做"。我们将代码封装成一个个对象,让它们各司其职。

本节内容:

  • 面向对象 vs 面向过程
  • 类 (Class) 与 对象 (Object) 的概念
  • 定义类与创建实例
  • 构造方法 __init__
  • 实例属性与实例方法
  • self 到底是个啥?
  • 实战练习

一、核心概念:类与对象

1.1 什么是类 (Class)?

类是对象的设计图纸或模板。它定义了一类事物共有的特征(属性)和行为(方法)。

例子:“狗” 是一个类。它有名字、品种(属性),会叫、会跑(行为)。

1.2 什么是对象 (Object)?

对象是根据类创建出来的具体实例。

例子:“我家那只叫旺财的哈士奇” 就是一个对象。它是"狗"这个类的一个具体存在。

#mermaid-svg-0R3kyCTvWQNS6z3a{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-0R3kyCTvWQNS6z3a .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-0R3kyCTvWQNS6z3a .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-0R3kyCTvWQNS6z3a .error-icon{fill:#552222;}#mermaid-svg-0R3kyCTvWQNS6z3a .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-0R3kyCTvWQNS6z3a .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-0R3kyCTvWQNS6z3a .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-0R3kyCTvWQNS6z3a .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-0R3kyCTvWQNS6z3a .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-0R3kyCTvWQNS6z3a .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-0R3kyCTvWQNS6z3a .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-0R3kyCTvWQNS6z3a .marker{fill:#333333;stroke:#333333;}#mermaid-svg-0R3kyCTvWQNS6z3a .marker.cross{stroke:#333333;}#mermaid-svg-0R3kyCTvWQNS6z3a svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-0R3kyCTvWQNS6z3a p{margin:0;}#mermaid-svg-0R3kyCTvWQNS6z3a g.classGroup text{fill:#9370DB;stroke:none;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:10px;}#mermaid-svg-0R3kyCTvWQNS6z3a g.classGroup text .title{font-weight:bolder;}#mermaid-svg-0R3kyCTvWQNS6z3a .nodeLabel,#mermaid-svg-0R3kyCTvWQNS6z3a .edgeLabel{color:#131300;}#mermaid-svg-0R3kyCTvWQNS6z3a .edgeLabel .label rect{fill:#ECECFF;}#mermaid-svg-0R3kyCTvWQNS6z3a .label text{fill:#131300;}#mermaid-svg-0R3kyCTvWQNS6z3a .labelBkg{background:#ECECFF;}#mermaid-svg-0R3kyCTvWQNS6z3a .edgeLabel .label span{background:#ECECFF;}#mermaid-svg-0R3kyCTvWQNS6z3a .classTitle{font-weight:bolder;}#mermaid-svg-0R3kyCTvWQNS6z3a .node rect,#mermaid-svg-0R3kyCTvWQNS6z3a .node circle,#mermaid-svg-0R3kyCTvWQNS6z3a .node ellipse,#mermaid-svg-0R3kyCTvWQNS6z3a .node polygon,#mermaid-svg-0R3kyCTvWQNS6z3a .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-0R3kyCTvWQNS6z3a .divider{stroke:#9370DB;stroke-width:1;}#mermaid-svg-0R3kyCTvWQNS6z3a g.clickable{cursor:pointer;}#mermaid-svg-0R3kyCTvWQNS6z3a g.classGroup rect{fill:#ECECFF;stroke:#9370DB;}#mermaid-svg-0R3kyCTvWQNS6z3a g.classGroup line{stroke:#9370DB;stroke-width:1;}#mermaid-svg-0R3kyCTvWQNS6z3a .classLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.5;}#mermaid-svg-0R3kyCTvWQNS6z3a .classLabel .label{fill:#9370DB;font-size:10px;}#mermaid-svg-0R3kyCTvWQNS6z3a .relation{stroke:#333333;stroke-width:1;fill:none;}#mermaid-svg-0R3kyCTvWQNS6z3a .dashed-line{stroke-dasharray:3;}#mermaid-svg-0R3kyCTvWQNS6z3a .dotted-line{stroke-dasharray:1 2;}#mermaid-svg-0R3kyCTvWQNS6z3a #compositionStart,#mermaid-svg-0R3kyCTvWQNS6z3a .composition{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-0R3kyCTvWQNS6z3a #compositionEnd,#mermaid-svg-0R3kyCTvWQNS6z3a .composition{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-0R3kyCTvWQNS6z3a #dependencyStart,#mermaid-svg-0R3kyCTvWQNS6z3a .dependency{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-0R3kyCTvWQNS6z3a #dependencyStart,#mermaid-svg-0R3kyCTvWQNS6z3a .dependency{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-0R3kyCTvWQNS6z3a #extensionStart,#mermaid-svg-0R3kyCTvWQNS6z3a .extension{fill:transparent!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-0R3kyCTvWQNS6z3a #extensionEnd,#mermaid-svg-0R3kyCTvWQNS6z3a .extension{fill:transparent!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-0R3kyCTvWQNS6z3a #aggregationStart,#mermaid-svg-0R3kyCTvWQNS6z3a .aggregation{fill:transparent!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-0R3kyCTvWQNS6z3a #aggregationEnd,#mermaid-svg-0R3kyCTvWQNS6z3a .aggregation{fill:transparent!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-0R3kyCTvWQNS6z3a #lollipopStart,#mermaid-svg-0R3kyCTvWQNS6z3a .lollipop{fill:#ECECFF!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-0R3kyCTvWQNS6z3a #lollipopEnd,#mermaid-svg-0R3kyCTvWQNS6z3a .lollipop{fill:#ECECFF!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-0R3kyCTvWQNS6z3a .edgeTerminals{font-size:11px;line-height:initial;}#mermaid-svg-0R3kyCTvWQNS6z3a .classTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-0R3kyCTvWQNS6z3a .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-0R3kyCTvWQNS6z3a .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-0R3kyCTvWQNS6z3a :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

实例化

实例化

Dog

+name

+breed

+bark()

旺财

来福


二、定义类与创建对象

在 Python 中,使用 class 关键字定义类。类名通常采用 驼峰命名法 (CamelCase),即首字母大写。

# 定义一个最简单的类
class Cat:
pass # 占位符,表示什么都不做

# 创建对象(实例化)
my_cat = Cat()
your_cat = Cat()

print(my_cat) # <__main__.Cat object at 0x…>
print(type(my_cat)) # <class '__main__.Cat'>


三、构造方法 __init__

仅仅创建一个空对象没什么用。我们需要在创建对象时,给它赋予一些初始状态(比如名字、年龄)。
这时就需要用到构造方法 __init__。

  • 它会在对象创建时自动调用。
  • 用于初始化对象的属性。

class Dog:
def __init__(self, name, age):
self.name = name # 将参数 name 赋值给对象的 name 属性
self.age = age
print(f"一只名叫 {name} 的小狗诞生了!")

# 创建对象时传参
dog1 = Dog("旺财", 3) # 自动调用 __init__
dog2 = Dog("来福", 2)

print(dog1.name) # 旺财
print(dog2.age) # 2


四、self 是什么?

初学者最头大的问题:为什么每个方法第一个参数都是 self?

  • self 代表对象本身。
  • 当你调用 dog1.bark() 时,Python 实际上是在执行 Dog.bark(dog1)。它自动把 dog1 这个对象传给了 self。
  • 通过 self.xxx,我们才能在类的方法内部访问该对象的属性。

注意:self 只是约定俗成的名字,你写成 this 也可以,但强烈建议不要这么做,会被同事打的。


五、实例方法:对象能做什么?

方法(Method)就是定义在类内部的函数。它的第一个参数必须是 self。

class Student:
def __init__(self, name, score):
self.name = name
self.score = score

# 定义方法
def study(self, course):
print(f"{self.name} 正在学习 {course}。")

def get_grade(self):
if self.score >= 60:
return "及格"
else:
return "不及格"

# 使用
s1 = Student("小明", 59)
s1.study("Python") # 输出: 小明 正在学习 Python。
print(s1.get_grade()) # 输出: 不及格


六、实战练习

练习1:银行账户类 (BankAccount)

设计一个类,包含:

  • 属性:owner (户主), balance (余额)
  • 方法:deposit (存款), withdraw (取款), show_info (显示信息)

class BankAccount:
def __init__(self, owner, balance=0):
self.owner = owner
self.balance = balance

def deposit(self, amount):
if amount > 0:
self.balance += amount
print(f"存入 {amount} 元,当前余额: {self.balance}")
else:
print("存款金额必须大于0")

def withdraw(self, amount):
if 0 < amount <= self.balance:
self.balance -= amount
print(f"取出 {amount} 元,当前余额: {self.balance}")
else:
print("余额不足或金额无效")

def show_info(self):
print(f"户主: {self.owner} | 余额: {self.balance}")

# 测试
my_account = BankAccount("Alice", 1000)
my_account.deposit(500) # 余额 1500
my_account.withdraw(2000) # 余额不足
my_account.withdraw(200) # 余额 1300

练习2:矩形类 (Rectangle)

设计一个类,初始化时传入宽和高,提供计算周长和面积的方法。

class Rectangle:
def __init__(self, width, height):
self.width = width
self.height = height

def area(self):
return self.width * self.height

def perimeter(self):
return 2 * (self.width + self.height)

rect = Rectangle(5, 10)
print(f"面积: {rect.area()}") # 50
print(f"周长: {rect.perimeter()}") # 30


七、常见问题

Q1:可以不写 __init__ 吗?

可以。如果不写,Python 会提供一个默认的空的构造方法。但通常我们需要初始化属性,所以绝大多数情况下都要写。

Q2:属性必须在 __init__ 里定义吗?

不一定,可以在任意方法中通过 self.new_attr = value 定义,但为了代码清晰,建议在 __init__ 中统一初始化所有的属性。

Q3:print(obj) 输出的一堆乱码是什么?

那是对象的内存地址。如果你想让它打印出好看的内容,需要用到 __str__ 方法(下一节课会讲)。


八、小结

#mermaid-svg-xHNAVbr8EWwWugLE{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-xHNAVbr8EWwWugLE .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-xHNAVbr8EWwWugLE .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-xHNAVbr8EWwWugLE .error-icon{fill:#552222;}#mermaid-svg-xHNAVbr8EWwWugLE .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-xHNAVbr8EWwWugLE .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-xHNAVbr8EWwWugLE .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-xHNAVbr8EWwWugLE .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-xHNAVbr8EWwWugLE .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-xHNAVbr8EWwWugLE .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-xHNAVbr8EWwWugLE .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-xHNAVbr8EWwWugLE .marker{fill:#333333;stroke:#333333;}#mermaid-svg-xHNAVbr8EWwWugLE .marker.cross{stroke:#333333;}#mermaid-svg-xHNAVbr8EWwWugLE svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-xHNAVbr8EWwWugLE p{margin:0;}#mermaid-svg-xHNAVbr8EWwWugLE .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-xHNAVbr8EWwWugLE .cluster-label text{fill:#333;}#mermaid-svg-xHNAVbr8EWwWugLE .cluster-label span{color:#333;}#mermaid-svg-xHNAVbr8EWwWugLE .cluster-label span p{background-color:transparent;}#mermaid-svg-xHNAVbr8EWwWugLE .label text,#mermaid-svg-xHNAVbr8EWwWugLE span{fill:#333;color:#333;}#mermaid-svg-xHNAVbr8EWwWugLE .node rect,#mermaid-svg-xHNAVbr8EWwWugLE .node circle,#mermaid-svg-xHNAVbr8EWwWugLE .node ellipse,#mermaid-svg-xHNAVbr8EWwWugLE .node polygon,#mermaid-svg-xHNAVbr8EWwWugLE .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-xHNAVbr8EWwWugLE .rough-node .label text,#mermaid-svg-xHNAVbr8EWwWugLE .node .label text,#mermaid-svg-xHNAVbr8EWwWugLE .image-shape .label,#mermaid-svg-xHNAVbr8EWwWugLE .icon-shape .label{text-anchor:middle;}#mermaid-svg-xHNAVbr8EWwWugLE .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-xHNAVbr8EWwWugLE .rough-node .label,#mermaid-svg-xHNAVbr8EWwWugLE .node .label,#mermaid-svg-xHNAVbr8EWwWugLE .image-shape .label,#mermaid-svg-xHNAVbr8EWwWugLE .icon-shape .label{text-align:center;}#mermaid-svg-xHNAVbr8EWwWugLE .node.clickable{cursor:pointer;}#mermaid-svg-xHNAVbr8EWwWugLE .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-xHNAVbr8EWwWugLE .arrowheadPath{fill:#333333;}#mermaid-svg-xHNAVbr8EWwWugLE .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-xHNAVbr8EWwWugLE .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-xHNAVbr8EWwWugLE .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-xHNAVbr8EWwWugLE .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-xHNAVbr8EWwWugLE .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-xHNAVbr8EWwWugLE .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-xHNAVbr8EWwWugLE .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-xHNAVbr8EWwWugLE .cluster text{fill:#333;}#mermaid-svg-xHNAVbr8EWwWugLE .cluster span{color:#333;}#mermaid-svg-xHNAVbr8EWwWugLE div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-xHNAVbr8EWwWugLE .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-xHNAVbr8EWwWugLE rect.text{fill:none;stroke-width:0;}#mermaid-svg-xHNAVbr8EWwWugLE .icon-shape,#mermaid-svg-xHNAVbr8EWwWugLE .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-xHNAVbr8EWwWugLE .icon-shape p,#mermaid-svg-xHNAVbr8EWwWugLE .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-xHNAVbr8EWwWugLE .icon-shape rect,#mermaid-svg-xHNAVbr8EWwWugLE .image-shape rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-xHNAVbr8EWwWugLE .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-xHNAVbr8EWwWugLE .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-xHNAVbr8EWwWugLE :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

面向对象 OOP

类 Class

对象 Object

图纸 / 模板

定义: class Dog:

实例 / 实体

创建: d = Dog()

核心要素

init (构造方法)

self (当前对象引用)

属性 (变量)

方法 (函数)

关键要点:

  • 类是工厂,对象是产品。
  • class 定义类,类名() 创建对象。
  • __init__ 是初始化方法,创建对象时自动跑。
  • self 是必须的,它指代调用该方法的对象本身。
  • 属性保存数据,方法定义行为。

  • 九、课后作业

  • 学生管理:创建一个 Student 类,包含姓名、年龄和成绩列表。提供一个方法 add_score(score) 添加成绩,一个方法 average_score() 计算平均分。
  • 红绿灯:创建一个 TrafficLight 类,包含颜色属性。提供一个 change() 方法切换颜色(红->绿->黄->红),并打印当前颜色。
  • 图书类:创建一个 Book 类,包含标题、作者、页数。实例化3本书,并将它们放入一个列表中,然后遍历列表打印每本书的标题。

  • 下节预告

    Day 15:面向对象编程(OOP)中篇 – 封装、继承与多态 – 我们将深入 OOP 的三大特性,学习如何保护数据安全,以及如何通过继承复用代码!


    系列导航:

    • 上一篇:Day 13 – 模块与包
    • 下一篇:Day 15 – 面向对象编程(中)(待更新)
    赞(0)
    未经允许不得转载:171主机测评 » Day 14:【99天精通Python】面向对象编程(OOP)上篇 - 类与对象
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址