Python3 面向对象详解

在 Python 中,面向对象编程(Object-Oriented Programming,OOP)是一种以 “对象” 为核心的编程范式,通过封装、继承、多态三大特性实现代码的复用、扩展和模块化。本文将系统解析 Python3 面向对象的核心概念与实战用法。

一、面向对象的基本概念

1. 什么是对象?

对象是现实世界实体的抽象,由属性(数据)和方法(行为)组成。例如:

  • 一个 “人” 可以是对象:属性(姓名、年龄),方法(说话、走路)。
  • 一个 “汽车” 可以是对象:属性(颜色、速度),方法(加速、刹车)。

2. 什么是类?

类是对象的模板,定义了对象的属性和方法。通过类可以创建多个具有相同结构的对象(实例)。
例如:“人类” 是类,“张三”“李四” 是该类的对象。

二、类与对象的定义和使用

1. 定义类

使用class关键字定义类,类名通常采用 “大驼峰命名法”(每个单词首字母大写)。
 
 
class Person:
    # 类属性:所有实例共享的属性
    species = "人类"  # 所有Person都是“人类”

    # 构造方法:初始化对象属性(__init__是特殊方法,称为“魔术方法”)
    def __init__(self, name, age):
        # 实例属性:每个对象独有的属性
        self.name = name  # self代表当前对象
        self.age = age

    # 实例方法:定义对象的行为
    def say_hello(self):
        print(f"大家好,我是{self.name},今年{self.age}岁")

    def grow(self):
        self.age += 1  # 修改实例属性
 

  • __init__:构造方法,创建对象时自动调用,用于初始化属性。
  • self:必须作为第一个参数,代表当前实例(类似 Java 的this)。

2. 创建对象(实例化)

通过 “类名 (参数)” 创建对象,参数对应__init__方法的参数(不含self)。
 
 
# 创建两个Person对象
p1 = Person("张三", 20)
p2 = Person("李四", 25)

# 访问对象的属性和方法
print(p1.name)  # 输出:张三
p1.say_hello()  # 输出:大家好,我是张三,今年20岁

p2.grow()
print(p2.age)   # 输出:26(年龄增长1岁)

# 访问类属性(所有实例共享)
print(p1.species)  # 输出:人类
print(Person.species)  # 输出:人类(也可通过类名访问)
 

三、类的核心组成

1. 属性分类

类型定义位置访问方式特点
实例属性 __init__方法中 对象.属性名 每个对象独立存储
类属性 类内部,方法外 类名.属性名对象.属性名 所有对象共享,节省内存

示例:类属性与实例属性的区别

class Student:
    school = "阳光小学"  # 类属性:所有学生的学校相同

    def __init__(self, name):
        self.name = name  # 实例属性:每个学生姓名不同

s1 = Student("小明")
s2 = Student("小红")

print(s1.school)  # 输出:阳光小学(共享类属性)
print(s2.school)  # 输出:阳光小学

Student.school = "星光小学"  # 修改类属性,所有实例都会受影响
print(s1.school)  # 输出:星光小学
 

2. 方法分类

Python 类中的方法分为三类,用途不同:

类型定义方式第一个参数调用方式用途
实例方法 def 方法名(self, ...) self 对象.方法名() 操作实例属性,依赖对象
类方法 @classmethod装饰 cls 类名.方法名() 操作类属性,不依赖对象
静态方法 @staticmethod装饰 无特殊参数 类名.方法名() 工具函数,与类 / 对象弱关联

示例:三种方法的使用

class Calculator:
    # 类属性:记录计算次数
    count = 0

    def __init__(self, a, b):
        self.a = a
        self.b = b

    # 实例方法:计算两个数的和(依赖实例属性)
    def add(self):
        return self.a + self.b

    # 类方法:更新计算次数(操作类属性)
    @classmethod
    def increment_count(cls):
        cls.count += 1

    # 静态方法:判断一个数是否为偶数(独立工具函数)
    @staticmethod
    def is_even(num):
        return num % 2 == 0

# 实例方法使用
calc = Calculator(3, 5)
print(calc.add())  # 输出:8

# 类方法使用
Calculator.increment_count()
Calculator.increment_count()
print(Calculator.count)  # 输出:2

# 静态方法使用
print(Calculator.is_even(4))  # 输出:True
 

四、面向对象的三大特性

1. 封装(Encapsulation)

核心思想:隐藏对象的内部细节,仅通过公开方法对外提供访问接口,确保数据安全。
Python 通过 “命名约定” 实现封装:

  • 公开属性 / 方法:默认命名(如namesay_hello),可直接访问。
  • 私有属性 / 方法:以双下划线__开头(如__secret),只能在类内部访问。

示例:私有属性的封装
 
class BankAccount:
    def __init__(self, account_id, balance):
        self.account_id = account_id  # 公开属性
        self.__balance = balance      # 私有属性(余额不允许直接修改)

    # 公开方法:提供安全的余额访问
    def get_balance(self):
        return self.__balance

    # 公开方法:提供安全的存款逻辑
    def deposit(self, amount):
        if amount > 0:
            self.__balance += amount
            print(f"存款成功,当前余额:{self.__balance}")
        else:
            print("存款金额必须为正数")

# 使用
account = BankAccount("622202XXXX", 1000)
print(account.account_id)  # 输出:622202XXXX(允许访问公开属性)

# 尝试直接访问私有属性(会报错)
# print(account.__balance)  # AttributeError: 'BankAccount' object has no attribute '__balance'

# 通过公开方法访问和修改
print(account.get_balance())  # 输出:1000
account.deposit(500)          # 输出:存款成功,当前余额:1500
 

注:Python 的私有属性并非绝对不可访问(可通过_类名__属性名间接访问,如account._BankAccount__balance),但这是不推荐的 “黑魔法”,违背封装原则。

2. 继承(Inheritance)

核心思想:子类(派生类)继承父类(基类)的属性和方法,并可扩展新功能或重写父类方法,实现代码复用。
(1)单继承
一个子类只能继承一个父类(Python 也支持多继承)。

# 父类:动物
class Animal:
    def __init__(self, name):
        self.name = name

    def eat(self):
        print(f"{self.name}在吃东西")

# 子类:狗(继承Animal)
class Dog(Animal):  # 通过括号指定父类
    # 重写父类方法(Override)
    def eat(self):
        print(f"{self.name}在啃骨头")  # 扩展父类的实现

    # 子类新增方法
    def bark(self):
        print(f"{self.name}在汪汪叫")

# 使用
dog = Dog("旺财")
dog.eat()   # 输出:旺财在啃骨头(调用重写后的方法)
dog.bark()  # 输出:旺财在汪汪叫(调用子类新增方法)
 
(2)调用父类方法
通过super()函数在子类中调用父类的方法(尤其是构造方法)。
class Parent:
    def __init__(self, a):
        self.a = a

class Child(Parent):
    def __init__(self, a, b):
        # 调用父类的__init__方法初始化a
        super().__init__(a)  # 等价于 Parent.__init__(self, a)
        self.b = b  # 子类新增属性

child = Child(10, 20)
print(child.a, child.b)  # 输出:10 20
 
(3)多继承
Python 支持一个子类继承多个父类,语法为class 子类(父类1, 父类2, ...)
但需注意方法解析顺序(MRO):当多个父类有同名方法时,按子类.__mro__的顺序查找。

class A:
    def say(self):
        print("A的say方法")

class B:
    def say(self):
        print("B的say方法")

class C(A, B):  # 继承A和B
    pass

c = C()
c.say()  # 输出:A的say方法(按MRO顺序,A在B前)
print(C.__mro__)  # 输出:(<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>)
 

3. 多态(Polymorphism)

核心思想:不同子类对同一方法有不同实现,通过父类引用调用时,表现出不同行为。
Python 的多态基于 “动态类型”(无需显式声明类型),更加灵活。
 
 
# 父类:形状
class Shape:
    def draw(self):
        pass  # 父类方法,子类需重写

# 子类:圆形
class Circle(Shape):
    def draw(self):
        print("画圆形")

# 子类:矩形
class Rectangle(Shape):
    def draw(self):
        print("画矩形")

# 统一接口:接收Shape类型(或其子类)
def draw_shape(shape):
    shape.draw()  # 调用时自动匹配子类的实现

# 多态体现:同一接口,不同实现
draw_shape(Circle())    # 输出:画圆形
draw_shape(Rectangle()) # 输出:画矩形
 

五、特殊方法(魔术方法)

Python 类中以双下划线__开头和结尾的方法称为 “特殊方法”(或 “魔术方法”),用于实现类的特殊行为(如运算符重载、字符串表示等)。

常用特殊方法

方法名作用示例场景
__init__ 构造方法,初始化对象 def __init__(self, name): ...
__str__ 定义对象的字符串表示(str(obj) print(obj) 时调用
__repr__ 定义对象的官方字符串表示(repr(obj) 调试时显示
__add__ 重载+运算符 obj1 + obj2 时调用
__len__ 重载len()函数 len(obj) 时调用

示例:自定义字符串表示和运算符
 
 
class Book:
    def __init__(self, title, pages):
        self.title = title
        self.pages = pages

    # 自定义print(book)的输出
    def __str__(self):
        return f"《{self.title}》({self.pages}页)"

    # 自定义len(book)的行为
    def __len__(self):
        return self.pages

    # 重载+运算符:两本书的总页数
    def __add__(self, other):
        return self.pages + other.pages

# 使用
book1 = Book("Python编程", 300)
book2 = Book("Java编程", 400)

print(book1)        # 输出:《Python编程》(300页)(调用__str__)
print(len(book1))   # 输出:300(调用__len__)
print(book1 + book2)# 输出:700(调用__add__)

六、面向对象的优势

  1. 代码复用:通过继承减少重复代码。
  2. 模块化:每个类独立封装属性和方法,便于维护。
  3. 可扩展性:新增功能只需添加子类或修改方法,符合 “开闭原则”。
  4. 可读性:类和对象的设计贴近现实世界,逻辑清晰。

总结

Python 的面向对象编程通过类与对象的封装、继承与多态,实现了代码的高效组织与扩展。核心要点包括:

  • 类是对象的模板,对象是类的实例;
  • 封装通过私有属性和公开方法保护数据;
  • 继承实现代码复用,super()用于调用父类方法;
  • 多态让不同子类通过统一接口表现不同行为;
  • 特殊方法增强类的灵活性(如运算符重载)。

掌握这些概念,能帮助你设计出更清晰、更易维护的 Python 程序,尤其在大型项目开发中体现显著优势。

posted on 2025-08-01 09:12  小陶coding  阅读(62)  评论(0)    收藏  举报