作者:还怪好嘞
发布时间:2026-05-29
难度:⭐⭐⭐⭐
预计阅读时间:30分钟
前言
面向对象编程(Object-Oriented Programming,OOP)是现代编程的核心范式之一。Python作为一门完全面向对象的语言,从设计之初就深度支持OOP思想。本文将深入讲解Python中类与对象的核心概念,从基础用法到底层实现原理,帮助你真正理解Python的面向对象机制。
一、知识点讲解
1.1 什么是面向对象编程
面向对象编程是一种程序设计思想,它将数据和操作数据的方法组织在一起,形成"对象"。与面向过程编程相比,OOP具有以下核心特性:
| 特性 | 说明 | 优势 |
|---|---|---|
| 封装 | 将数据和方法包装在类中 | 隐藏实现细节,提高安全性 |
| 继承 | 子类继承父类的属性和方法 | 代码复用,层次清晰 |
| 多态 | 同一接口,不同实现 | 灵活扩展,降低耦合 |
1.2 类的定义与实例化
类是创建对象的蓝图,定义了对象应有的属性和方法:
# 定义一个简单的类
class Dog:
"""狗类,表示一只狗。"""
# 类属性:所有实例共享
species = "Canis familiaris"
def __init__(self, name, age):
"""初始化方法(构造器)。
Args:
name: 狗的名字
age: 狗的年龄
"""
# 实例属性:每个实例独立
self.name = name
self.age = age
def description(self):
"""返回狗的描述信息。"""
return f"{
self.name} is {
self.age} years old"
def speak(self, sound):
"""让狗发出声音。"""
return f"{
self.name} says: {
sound}"
# 创建实例(对象)
my_dog = Dog("Buddy", 3)
# 访问属性和方法
print(my_dog.name) # Buddy
print(my_dog.description()) # Buddy is 3 years old
print(my_dog.speak("Woof!")) # Buddy says: Woof!
1.3 init 方法详解
__init__是类的构造方法,在创建实例时自动调用:
class Person:
"""人类。"""
def __init__(self, name, age=0, email=None):
"""初始化方法支持默认参数。
Args:
name: 姓名(必需)
age: 年龄(可选,默认0)
email: 邮箱(可选,默认None)
"""
self.name = name
self.age = age
self.email = email
self._is_active = True # 内部状态
# 可以在初始化时执行其他操作
print(f"创建了Person对象: {
self.name}")
def __del__(self):
"""析构方法,对象被销毁时调用(不常用)。"""
print(f"Person对象 {
self.name} 被销毁")
# 不同方式创建实例
p1 = Person("Alice") # 只提供必需参数
p2 = Person("Bob", 25) # 提供部分可选参数
p3 = Person("Carol", 30, "carol@example.com") # 提供所有参数
p4 = Person("David", email="david@test.com") # 使用关键字参数
1.4 self 参数的本质
self代表类的实例本身,是Python类方法的第一个参数:
class Example:
def method(self, x):
"""实例方法,第一个参数是实例本身。"""
print(f"self is: {
self}")
print(f"x is: {
x}")
return x * 2
# 调用方式1:通过实例调用(推荐)
obj = Example()
result = obj.method(5) # Python自动将obj作为self传入
# 调用方式2:通过类调用(需要手动传入实例)
result = Example.method(obj, 5) # 等价于上面的调用
重要理解:self不是Python关键字,你可以使用其他名称,但强烈建议遵循约定使用self。
1.5 类属性 vs 实例属性
class Counter:
"""计数器类,演示类属性和实例属性的区别。"""
# 类属性:所有实例共享
count = 0
def __init__(self):
# 实例属性:每个实例独立
self.instance_count = 0
def increment(self):
"""增加计数。"""
Counter.count += 1 # 修改类属性
self.instance_count += 1 # 修改实例属性
@classmethod
def get_class_count(cls):
"""获取类计数。"""
return cls.count
# 演示类属性和实例属性的区别
c1 = Counter()
c2 = Counter()
c1.increment()
c1.increment()
c2.increment()
print(f"c1.instance_count: {
c1.instance_count}") # 2
print(f"c2.instance_count: {
c2.instance_count}") # 1
print(f"Counter.count: {
Counter.count}") # 3(两个实例共享)
print(f"c1.count: {
c1.count}") # 3
print(f"c2.count: {
c2.count}") # 3
关键区别:
| 特性 | 类属性 | 实例属性 |
|---|---|---|
| 定义位置 | 类体中 | __init__中 |
| 共享性 | 所有实例共享 | 每个实例独立 |
| 访问方式 | ClassName.attr或self.attr |
self.attr |
| 修改影响 | 影响所有实例 | 只影响当前实例 |
1.6 访问控制与命名修饰
Python没有像Java那样的严格访问控制,但使用命名约定来实现类似效果:
class BankAccount:
"""银行账户类,演示访问控制。"""
bank_name = "Python Bank" # 公有类属性
_total_accounts = 0 # 保护属性(约定)
def __init__(self, owner, balance=0):
self.owner = owner # 公有属性
self._balance = balance # 保护属性(单下划线)
self.__transaction_log = [] # 私有属性(双下划线)
BankAccount._total_accounts += 1
def deposit(self, amount):
"""存款(公有方法)。"""
if amount > 0:
self._balance += amount
self.__log_transaction(f"Deposit: +{
amount}")
return True
return False
def withdraw(self, amount):
"""取款(公有方法)。"""
if 0 < amount <= self._balance:
self._balance -= amount
self.__log_transaction(f"Withdrawal: -{
amount}")
return True
return False
def _calculate_interest(self, rate):
"""计算利息(保护方法)。"""
return self._balance * rate
def __log_transaction(self, message):
"""记录交易(私有方法)。"""
self.__transaction_log.append(message)
def get_balance(self):
"""获取余额。"""
return self._balance
def get_transaction_log(self):
"""获取交易记录(受控访问)。"""
return self.__transaction_log.copy()
# 访问控制演示
account = BankAccount("Alice", 1000)
# 公有属性和方法 - 正常访问
print(account.owner) # Alice
account.deposit(500)
# 保护属性 - 可以访问但不建议
print(account._balance) # 1500(但不应该直接访问)
# 私有属性 - 名称修饰后访问
# print(account.__transaction_log) # AttributeError
print(account._BankAccount__transaction_log) # 可以访问但不推荐
# 查看名称修饰
print(dir(account)) # 可以看到 _BankAccount__transaction_log
命名修饰(Name Mangling)机制:
- 双下划线开头的属性会被改名为
_ClassName__attribute - 这是为了防止子类意外覆盖父类的私有属性
- 不是真正的私有化,只是约定和机制的结合
二、底层原理
2.1 type、object、class的三角关系
Python中的一切都是对象,理解type、object和class的关系是掌握Python面向对象的关键:
# 探索Python的对象模型
class MyClass:
pass
obj = MyClass()
# 1. 对象的类型
print(type(obj)) # <class '__main__.MyClass'>
print(type(MyClass)) # <class 'type'>
print(type(type)) # <class 'type'> type是它自己的类型
# 2. 类的基类
print(MyClass.__bases__) # (<class 'object'>,)
print(type.__bases__) # (<class 'object'>,)
print(object.__bases__) # () object是所有类的基类
# 3. 对象的关系
print(isinstance(obj, MyClass)) # True
print(isinstance(obj, object)) # True
print(issubclass(MyClass, object)) # True
print(issubclass(type, object)) # True
# 4. 关键结论
print(type(object)) # <class 'type'> object是type的实例
print(isinstance(type, type)) # True type是它自己的实例
核心关系图:
┌─────────────────────────────────────────────────────────┐
│ object │
│ (所有类的基类) │
│ ┌─────────────────────────────────────────────────┐ │
│ │ type │ │
│ │ (所有类的类型,包括它自己) │ │
│ │ ┌─────────────────────────────────────────┐ │ │
│ │ │ MyClass │ │ │
│ │ │ (用户定义的类,type的实例) │ │ │
│ │ │ ┌─────────────────────────────────┐ │ │ │
│ │ │ │ obj │ │ │ │
│ │ │ │ (MyClass的实例) │ │ │ │
│ │ │ └─────────────────────────────────┘ │ │ │
│ │ └─────────────────────────────────────────┘ │ │
│ └─────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────┘
核心规则:
type是自身的实例(type(type) is type)object是type的实例(type(object) is type)type继承自object(

—— 类与对象&spm=1001.2101.3001.5002&articleId=161295331&d=1&t=3&u=bf56d262cfdb4250b9dd34d726309af1)

被折叠的 条评论
为什么被折叠?



