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 (当前对象引用)
属性 (变量)
方法 (函数)
关键要点:
九、课后作业
下节预告
Day 15:面向对象编程(OOP)中篇 – 封装、继承与多态 – 我们将深入 OOP 的三大特性,学习如何保护数据安全,以及如何通过继承复用代码!
系列导航:
- 上一篇:Day 13 – 模块与包
- 下一篇:Day 15 – 面向对象编程(中)(待更新)






