Python全栈修炼之路 | 第10篇:面向对象编程(上)—— 类与对象

作者:还怪好嘞
发布时间: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.attrself.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中的一切都是对象,理解typeobjectclass的关系是掌握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的实例)              │    │    │    │
│  │  │  └─────────────────────────────────┘    │    │    │
│  │  └─────────────────────────────────────────┘    │    │
│  └─────────────────────────────────────────────────┘    │
└─────────────────────────────────────────────────────────┘

核心规则

  1. type是自身的实例(type(type) is type
  2. objecttype的实例(type(object) is type
  3. type继承自object
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值