当前位置:首页>python>python面向对象编程(一)——类与对象

python面向对象编程(一)——类与对象

  • 2026-09-02 17:15:56
python面向对象编程(一)——类与对象

本周目标

  • 理解面向对象编程(OOP) 的基本思想
  • 掌握类(Class) 和对象(Object) 的核心概念
  • 学会定义类、创建对象、添加属性和方法
  • 理解 __init__ 构造方法和 self 的作用

一、从“面向过程”到“面向对象”的思维转变

之前我们一直在用面向过程的方式编程——把程序看作一系列按顺序执行的操作步骤。

而面向对象编程(OOP) 则把现实世界映射到代码中:用类(Class) 描述一类事物的“蓝图”,用对象(Object) 表示具体的实体。就像现实中“人”是一个抽象概念,而“张三”是一个具体的人一样。

OOP 在 AI 领域无处不在:

  • PyTorch 中,你定义的每一个神经网络模型都是继承自 nn.Module 类的对象
  • 数据集中,每个样本可以是一个对象,包含特征和标签
  • 训练过程中,优化器、损失函数、数据加载器都是对象

💡 核心转变:面向过程关注“怎么做”(算法步骤),面向对象关注“谁来做”(数据和行为的主体)。

二、类与对象——从“图纸”到“实物”的构建

1. 什么是类?什么是对象?

类(Class) 就像一张建筑设计图纸——它定义了房子应该有什么结构(属性)和能做什么(方法),但图纸本身不是房子。

对象(Object) 就是根据这张图纸建造出来的真实房子——每栋房子都有具体的位置、面积、居住者,而且可以执行开门、关门等操作。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 定义一个“狗”类(图纸)class Dog:    # 属性(特征)    def __init__(self, name, breed):        self.name = name        self.breed = breed    # 方法(行为)    def bark(self):        print(f"{self.name} 汪汪叫!")# 创建对象(根据图纸建造实物)dog1 = Dog("旺财", "金毛")    # 一个具体的狗dog2 = Dog("小黑", "泰迪")    # 另一个具体的狗# 调用对象的方法dog1.bark()  # 旺财 汪汪叫!dog2.bark()  # 小黑 汪汪叫!

2. 类的定义语法

1
2
3
4
5
6
7
8
9
10
11
12
class 类名:    """文档字符串(可选)"""    def __init__(self, 参数1, 参数2, ...):        """构造方法:创建对象时自动调用,用于初始化属性"""        self.属性名1 = 参数1        self.属性名2 = 参数2    def 方法名(self, 其他参数):        """普通方法:描述对象的行为"""        # 可以通过 self 访问对象的属性        pass

⚠️ 命名规范:类名使用大驼峰命名法(如 Student、NeuralNetwork),而变量名和函数名使用小写加下划线(如 student_name、calculate_score)。

三、__init__ 与 self —— 面向对象的“灵魂”

1. __init__ 构造方法

__init__ 是 Python 类的构造方法,在创建对象时自动调用,用于初始化对象的属性。

1
2
3
4
5
6
7
8
9
10
class Student:    def __init__(self, name, age, score):        print(f"正在创建学生:{name}")        self.name = name        self.age = age        self.score = score# 创建对象时,__init__ 自动执行s1 = Student("张三", 20, 95)   # 输出:正在创建学生:张三s2 = Student("李四", 22, 88)   # 输出:正在创建学生:李四

2. self —— 指向“我”自己

self 是 Python 类方法的第一个参数,代表当前对象本身。通过 self,方法可以访问和操作当前对象的属性和其他方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Car:    def __init__(self, brand, color):        self.brand = brand   # self.brand 是对象的属性,brand 是传入的参数        self.color = color        self.mileage = 0     # 可以设置默认值    def drive(self, distance):        self.mileage += distance   # 通过 self 修改属性        print(f"{self.color}色的{self.brand}行驶了{distance}公里")    def show_info(self):        print(f"品牌:{self.brand},颜色:{self.color},里程:{self.mileage}公里")# 使用my_car = Car("特斯拉", "红色")my_car.drive(100)      # 红色色的特斯拉行驶了100公里my_car.drive(50)       # 红色色的特斯拉行驶了50公里my_car.show_info()     # 品牌:特斯拉,颜色:红色,里程:150公里

⚠️ 新手常见误区:

  1. 在方法中忘记写 self 参数 → 调用时报错 missing 1 required positional argument
  2. 在方法中访问属性时忘记加 self. → 会被当作局部变量处理,逻辑出错

四、类的属性和方法详解

1. 实例属性 vs 类属性

实例属性:属于每个对象自己的数据,通过 self.属性名 定义,每个对象独立。类属性:属于类本身的数据,所有对象共享,在类中直接定义。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Employee:    # 类属性(所有员工共享)    company = "AI科技公司"    total_employees = 0    def __init__(self, name, salary):        # 实例属性(每个员工独有)        self.name = name        self.salary = salary        Employee.total_employees += 1  # 每创建一个员工,总数+1# 访问类属性(可以通过类名,也可以通过实例)print(Employee.company)           # AI科技公司e1 = Employee("张三", 10000)e2 = Employee("李四", 12000)print(e1.company)                 # AI科技公司(实例也可以访问类属性)print(Employee.total_employees)   # 2

2. 实例方法 vs 类方法 vs 静态方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
class MathUtils:    pi = 3.14159  # 类属性    def __init__(self, version):        self.version = version  # 实例属性    # 实例方法:最常用,通过 self 访问实例属性    def get_version(self):        return self.version    # 类方法:通过 cls 访问类属性,用 @classmethod 装饰    @classmethod    def get_pi(cls):        return cls.pi    # 静态方法:不需要 self 或 cls,用 @staticmethod 装饰(只是一个普通函数放在类里)    @staticmethod    def add(a, b):        return a + b# 调用utils = MathUtils("v1.0")print(utils.get_version())    # v1.0(实例方法)print(MathUtils.get_pi())     # 3.14159(类方法)print(MathUtils.add(3, 5))    # 8(静态方法)

💡 AI小贴士:在 AI 框架中,类方法常用于创建预训练模型(如 BertModel.from_pretrained()),静态方法常用于工具函数(如 torch.cat())。

五、封装 —— 让数据更安全

封装(Encapsulation) 是 OOP 的三大特性之一,指把数据和操作数据的方法绑定在一起,并隐藏内部实现细节,只暴露必要的接口。

1. 私有属性和方法(命名约定)

Python 通过命名约定来实现“私有”:

  • _name(单下划线开头):保护属性,表示“不要直接访问”(只是约定,实际上仍可访问)
  • __name(双下划线开头):私有属性,Python 会进行名称修饰(Name Mangling),防止被子类覆盖
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
class BankAccount:    def __init__(self, owner, balance):        self.owner = owner        self.__balance = balance  # 私有属性(双下划线)    def deposit(self, amount):        if amount > 0:            self.__balance += amount            print(f"存入 {amount},当前余额:{self.__balance}")    def withdraw(self, amount):        if 0 < amount <= self.__balance:            self.__balance -= amount            print(f"取出 {amount},当前余额:{self.__balance}")        else:            print("余额不足或金额无效")    def get_balance(self):        """通过公开方法获取余额(封装了内部实现)"""        return self.__balanceaccount = BankAccount("张三", 1000)account.deposit(500)      # 存入 500,当前余额:1500account.withdraw(200)     # 取出 200,当前余额:1300# print(account.__balance)  # ❌ AttributeError(私有属性不能直接访问)print(account.get_balance())  # 1300(通过公开方法访问)

💡 封装的价值:你可以随时修改 __balance 的存储方式(比如改为数据库存储),而使用 get_balance() 的代码完全不受影响——这就是“接口不变,实现可改”。

2. 使用 @property 实现优雅的访问控制

@property 装饰器可以把方法变成“属性”来访问,语法更优雅:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class Person:    def __init__(self, name, age):        self.name = name        self._age = age  # 受保护的属性    @property    def age(self):        """将 age 方法变成属性,通过 person.age 访问"""        return self._age    @age.setter    def age(self, value):        """通过 person.age = 新值 来设置,可以添加验证逻辑"""        if value < 0 or value > 150:            raise ValueError("年龄必须在 0-150 之间")        self._age = valuep = Person("张三", 25)print(p.age)   # 25(像访问属性一样,不用加括号)p.age = 26     # 像设置属性一样print(p.age)   # 26# p.age = -5   # ❌ ValueError

六、 闲谈

python非常信任开发者,类中私有属性只是名称被改写了。

1
2
3
4
5
6
7
8
9
10
11
12
class BankAccount:    def __init__(self, owner, balance):        self.owner = owner        self.__balance = balance  # 私有属性(双下划线)    def get_balance(self):        """通过公开方法获取余额(封装了内部实现)"""        return self.__balanceaccount = BankAccount("张三", 1000)# print(account.__balance)  # ❌ AttributeError(私有属性不能直接访问)account._BankAccount__balance =999999999print(account.get_balance())  # 999999999(通过公开方法访问)

本周小结

本周我们正式进入面向对象编程的世界:

知识点
核心要点
类与对象
类是蓝图,对象是实例。用 class 类名: 定义,用 对象名 = 类名() 创建
__init__
构造方法,创建对象时自动调用,用于初始化属性
self
代表当前对象,通过 self.属性 访问对象的数据
实例属性 vs 类属性
实例属性每个对象独有,类属性所有对象共享
实例方法 vs 类方法 vs 静态方法
分别用 self、@classmethod、@staticmethod 定义
封装
用 __属性 实现私有,用 @property 实现优雅的访问控制
OOP 的价值
代码结构清晰、易于维护、可扩展性强

下周预告:我们将继续深入面向对象编程,学习继承(Inheritance) 和多态(Polymorphism)——这是 OOP 的核心魅力所在,能让代码实现“一次编写,到处扩展”的效果!


面向对象编程是程序员思维的一次重要跃升——从“写代码”到“设计系统”。好好消化本周内容,它将影响你之后所有编程的思维方式! 🚀

最新文章

随机文章