在软件开发中,面向对象编程(Object-Oriented Programming,简称 OOP)是一种非常常见也非常重要的编程思想。它借鉴了人们对现实世界的理解方式:我们生活中接触的事物,比如一只狗、一辆汽车、一个学生,都是“对象”。每个对象都有自己的属性(例如狗的名字、年龄)和行为(例如狗会叫、会跑)。面向对象编程就是把这些事物抽象成“对象”,用程序来模拟现实世界中的数据和操作。
在 Python 中,对象的蓝图就是“类(Class)”,而通过类创建出的具体个体,就是“对象(Object)”。学习如何定义类、创建对象、封装属性和行为,是掌握 Python 面向对象编程的第一步。
目录
一、面向对象编程
1. 什么是面向对象编程(OOP)
2. 面向对象的三大特征
3. 面向对象 vs 面向过程
4. Python 中的面向对象示例
二、类和对象
1. 类与对象的概念
1.1 什么是类(Class)?
1.2 什么是对象(Object)?
2. 如何定义类
3. 实例化对象
4. 类 vs 对象 对比表
三、属性
1 . 实例属性(对象属性)
2 . 类属性
3 . 实例属性与类属性对比
四、方法
1.实例方法(Instance Method)
1.1. 初始化方法 __init__
1.2. self
2. 类方法 @classmethod
3. 静态方法
3.1 什么是静态方法?
3.2 语法格式:
3.3 使用场景:
4. 对比:实例方法 / 类方法 / 静态方法
5. 真实案例:格式验证类
6. 三种方法调用总结:
7. 各种方法的应用场景
7.1实例方法的应用场景
7.2类方法的应用场景
7.2.1 修改类属性:改变所有实例共享的值。
7.2.2 创建备用构造器(常见设计模式):用字符串、字典等构建对象。
7.3 静态方法的应用场景
8.魔术方法
8.1 什么是魔术方法
8.2 魔术方法命名规则
8.3 常见魔术方法及作用
8.4 示例:自定义 __str__ 和 __len__
8.5 魔术方法的意义
面向对象编程(OOP:Object-Oriented Programming)是一种程序设计思想,它将程序结构组织为由“对象”组成的系统。这种方式把数据和行为打包在一起,更贴近现实世界建模。
通俗解释:
现实世界中所有事物(人、车、手机等)都可以抽象为对象。每个对象有:
属性(数据):如人的姓名、年龄,车的颜色、型号
行为(功能):如人会说话、车能启动、手机能打电话
OOP 的核心思想是:
用“类”抽象对象,封装属性和行为,映射现实世界,构建程序结构。
特性 | 含义 | 示例 |
---|---|---|
封装 | 把数据和方法绑定在一起,隐藏内部细节 | 手机发短信时不必知道其内部运作机制 |
继承 | 子类可继承父类的属性和方法,实现代码复用 | 学生类继承人类的属性(姓名、年龄) |
多态 | 相同的方法名,不同对象有不同表现 | 动物类的 speak() 方法,狗叫、猫叫各不同 |
编程思想 | 特点 | 示例 |
---|---|---|
面向过程 | 强调“过程”与“步骤” | 做饭流程:洗菜→切菜→炒菜 |
面向对象 | 强调“对象”与“行为” | 做饭由厨师对象执行各种方法 |
class Dog:
def __init__(self, name):
self.name = name
def bark(self):
print(f"{self.name}:汪汪!")
# 创建对象
dog1 = Dog("小黑")
dog2 = Dog("旺财")
# 调用行为
dog1.bark()
dog2.bark()
输出:
小黑:汪汪!
旺财:汪汪!
为什么使用面向对象
更贴近现实建模,易于理解
更好的代码重用性(通过继承)
更高的可维护性(封装与模块化)
支持复杂大型项目开发(便于协作)
类是对一类事物的抽象模板,定义了这类事物具有的属性(数据)和行为(方法)。
类 = 属性(名词)+ 方法(动词) 例如:“学生”就是一种类,它有:
属性:姓名、年龄、学号
方法:学习、考试、自我介绍
对象是根据类创建的具体实例,每个对象都有属于自己的属性和行为。
例如:
类是“学生模板”
对象是“小明”“小红”这些具体学生
在 Python 中使用 class
关键字定义类:
class Student:
def __init__(self, name, age):
self.name = name # 属性
self.age = age
def introduce(self): # 方法
print(f"我是{self.name},今年{self.age}岁。")
说明:
__init__
是构造方法,在对象创建时自动调用,用来初始化属性
self
表示“当前对象本身”
所谓“实例化”,就是根据类创建对象(也叫实例)。
stu1 = Student("小明", 18)
stu2 = Student("小红", 20)
此时:
stu1
是 Student
类的一个对象,表示一个18岁的学生小明
stu2
是另一个对象,表示20岁的学生小红
你可以调用对象的方法来使用它的功能:
stu1.introduce()
stu2.introduce()
输出:
我是小明,今年18岁。
我是小红,今年20岁。
概念 | 类(Class) | 对象(Object) |
---|---|---|
定义 | 模板或蓝图 | 模板生成的具体实例 |
含义 | 抽象,描述某类事物的属性和行为 | 具体,拥有类的所有特征 |
示例 | class Student: |
stu = Student("小明", 18) |
功能 | 用于定义属性、方法 | 用于实际使用这些属性和方法 |
类是抽象的模板,对象是真实存在的事物。实例化就是用类创建对象的过程。
定义在
__init__
方法内部,使用self.属性名
。每个实例拥有自己独立的一套属性。
通过对象访问。
示例:
class Student:
def __init__(self, name, age):
self.name = name # 实例属性
self.age = age
# 创建实例
s1 = Student("Alice", 20)
s2 = Student("Bob", 22)
print(s1.name, s1.age) # Alice 20
print(s2.name, s2.age) # Bob 22
说明:
self.name
和self.age
是实例属性。不同对象的属性值互不影响。
访问方式:
只能通过实例对象来访问。
p1 = Person("Alice", 25)
print(p1.name) # 输出:Alice
print(p1.age) # 输出:25
定义在类体中,位于所有方法之外。
属于类本身,所有实例共享。
可以通过类或对象访问。
示例:
class Student:
school = "清华大学" # 类属性
def __init__(self, name):
self.name = name # 实例属性
s1 = Student("Alice")
s2 = Student("Bob")
print(s1.school) # 清华大学
print(s2.school) # 清华大学
print(Student.school) # 清华大学
说明:
school
是类属性,所有对象共享一个值。
注意事项:
s1.school = "北京大学" # 给 s1 添加了一个新的实例属性,不会影响类属性
print(s1.school) # 北京大学(实例属性)
print(s2.school) # 清华大学(仍是类属性)
print(Student.school) # 清华大学(类属性未变)
访问方式:
类属性既可以通过类名访问,也可以通过实例对象访问。
print(Person.species) # 通过类访问,输出:Human
p1 = Person("Alice")
print(p1.species) # 通过实例访问,输出:Human
比较项 | 实例属性 | 类属性 |
---|---|---|
定义位置 | 类的 __init__ 方法中 |
类体中,所有方法之外 |
所属对象 | 属于每个对象(实例) | 属于类本身 |
是否共享 | 每个实例独立 | 所有实例共享 |
访问方式 | 对象.属性名 |
类名.属性名 或 对象.属性名 |
作用:
实例方法作用于对象实例,用于操作实例属性或执行与该实例相关的行为。
必须通过对象调用,是最常用的类中方法类型。
特点:
不需要额外的装饰器(如
@staticmethod
、@classmethod
)。第一个参数必须为
self
,代表当前调用该方法的对象本身。可以访问和修改该对象的属性。
示例:
class Student:
def __init__(self, name, age):
self.name = name # 实例属性
self.age = age
def introduce(self): # 实例方法
print(f"大家好,我是{self.name},今年{self.age}岁。")
# 创建对象
stu = Student("小明", 18)
# 调用实例方法
stu.introduce()
输出:
大家好,我是小明,今年18岁。
__init__
作用:
用于创建对象时初始化属性。
是一个特殊的 实例方法,在类实例化时自动调用。
特点:
方法名固定为
__init__
。第一个参数必须是
self
,代表当前实例对象。常用于定义实例属性。
示例:
class Student:
def __init__(self, name, age):
self.name = name # 实例属性
self.age = age
s = Student("Alice", 20)
print(s.name) # 输出:Alice
问题 | 回答 |
---|---|
为什么要定义 __init__ ? |
为了在对象创建时自动初始化属性,确保每个对象出生时是有效的 |
为什么方法第一个参数必须是 self ? |
因为 Python 自动把调用者对象传给它,方法需要知道是哪个对象在调用,从而访问或修改这个对象的属性 |
@classmethod
作用:
类方法作用于类本身,而不是某个实例。
通常用于操作类属性或创建类的备用构造方法。
可以在不创建对象的情况下访问类方法。
特点:
使用装饰器
@classmethod
装饰。第一个参数固定为
cls
,代表当前类本身(类似实例方法中的self
)。
示例:
class Student:
school = "清华大学" # 类属性
def __init__(self, name):
self.name = name
@classmethod
def change_school(cls, new_school):
cls.school = new_school
print(Student.school) # 清华大学
Student.change_school("北京大学")
print(Student.school) # 北京大学
静态方法是定义在类中,但不依赖类和实例的属性和方法的函数。
不需要 self
或 cls
作为第一个参数。
本质上是与类相关的工具函数。
class ClassName:
@staticmethod
def method_name(...):
...
当函数逻辑与类有关联,但不需要访问类属性或实例属性时,就适合使用静态方法。
常用作工具类方法、计算函数等。
示例:
class MathUtils:
@staticmethod
def add(a, b):
return a + b
# 调用方式(推荐使用类名调用)
print(MathUtils.add(3, 5)) # 输出:8
# 也可以通过实例调用
utils = MathUtils()
print(utils.add(10, 2)) # 输出:12
方法类型 | 装饰器 | 第一个参数 | 用途 | 是否能访问类属性 | 是否能访问实例属性 |
---|---|---|---|---|---|
实例方法 | 无 | self |
操作对象的状态(实例属性) | 否 | 是 |
类方法 | @classmethod |
cls |
操作类的状态(类属性) | 是 | 否 |
静态方法 | @staticmethod |
无 | 工具函数,逻辑与类相关,但不依赖类或对象 | 否 | 否 |
class Validator:
@staticmethod
def is_email(text):
return '@' in text and '.' in text
print(Validator.is_email("[email protected]")) # True
print(Validator.is_email("invalid")) # False
说明:
is_email
不依赖类或实例的属性,仅仅执行一段逻辑判断,因此适合作为静态方法。
方法类型 | 推荐调用方式 |
---|---|
实例方法 | 实例对象调用 |
类方法 | 类名调用 |
静态方法 | 类名调用 |
特点:
用
self
引用当前对象实例。常用于操作和访问实例的属性。
典型应用场景:
定义对象行为,如学生介绍、账户充值、订单支付等。
class User:
def __init__(self, name):
self.name = name
def greet(self):
print(f"Hello, I am {self.name}")
特点:
用
cls
引用当前类。可以访问/修改类属性。
常用于创建“备用构造器”。
@classmethod
def set_school(cls, school_name):
cls.school = school_name
class Book:
def __init__(self, title, price):
self.title = title
self.price = price
@classmethod
def from_string(cls, info_str):
title, price = info_str.split('-')
return cls(title, float(price))
b = Book.from_string("Python入门-88.8")
print(b.title, b.price)
特点:
不需要 self
或 cls
。
不访问类属性,也不访问实例属性。
和类逻辑有关的通用工具函数。
典型应用场景:
提供工具方法,如格式校验、数学计算、日期处理等。
class Validator:
@staticmethod
def is_email(text):
return "@" in text and "." in text
魔术方法是前后带有双下划线的特殊方法,例如 __init__
、__str__
、__add__
等。
Python 会在特定情况下自动调用它们
可以通过重写这些方法,自定义类的行为,使其更像内置类型
所有魔术方法都以 __方法名__
的形式命名,例如:
def __init__(self, ...): ...
def __str__(self): ...
def __len__(self): ...
方法名 | 触发时机 | 作用说明 |
---|---|---|
__init__ |
创建对象时 | 初始化对象 |
__str__ |
print(obj) |
定义对象的字符串表现形式 |
__repr__ |
在解释器中显示对象 | 返回对象的“官方字符串” |
__len__ |
使用 len(obj) 时 |
自定义对象的长度 |
__add__ |
对象使用 + 时 |
自定义加法操作 |
__eq__ |
对象使用 == 时 |
自定义相等性比较 |
__str__
和 __len__
class Book:
def __init__(self, title, pages):
self.title = title
self.pages = pages
def __str__(self):
return f"《{self.title}》共{self.pages}页"
def __len__(self):
return self.pages
book = Book("Python编程", 300)
print(book) # 自动调用 __str__
print(len(book)) # 自动调用 __len__
输出:
《Python编程》共300页
300
魔术方法让你创建的对象行为像内置类型一样:
使用
print(obj)
有清晰输出 →__str__
使用
len(obj)
获取长度 →__len__
使用
+
,==
运算符 →__add__
,__eq__