面向对象编程(OOP)详解

一、什么是面向对象编程?

面向对象编程(Object-Oriented Programming,简称 OOP)是一种重要的编程风格,它与其他编程风格(如面向过程、指令式编程、函数式编程)共同构成了主流的编程范式。

  • 面向过程:以 C 语言为代表,强调任务执行的顺序和过程,通过函数分步实现任务,适用于简单任务。
  • 面向对象:将任务拆分为不同对象,每个对象封装特定数据和行为,通过对象交互完成任务,更注重程序设计和可维护性,适用于复杂任务。

特性面向过程面向对象
基本单位函数或过程对象(通过类实例化)
数据和行为的关系数据和行为分开数据和行为封装在对象中
设计方式强调功能和线性执行过程强调对象交互和消息传递
可扩展性较差,难以应对复杂结构较好,易于扩展和修改
易维护性复杂系统中难以维护模块化程度高,便于维护

面向对象的三大核心基石是:封装继承多态

二、封装(Encapsulation)

封装是指将类的属性私有化,仅通过公开方法对外提供访问接口,从而保证数据安全并屏蔽实现细节。

1. 类的概念

类是对具有相同特征(属性)和行为(方法)的事物的抽象描述。

  • 特征(属性):通常是名词(如狗的年龄、品种)。
  • 行为(方法):通常是动词(如狗的 “叫”、“跑”)。

类是抽象的模板,而对象是类的具体实例(例如,“狗” 是类,“我家的金毛犬” 是对象)。

2. 类的定义与对象创建

(1)类的定义

使用 class 关键字定义类,类名采用大驼峰命名法(如 DogPersonInfo)。

python

class Dog:
    # 类的属性和方法定义
    pass
(2)__init__ 初始化方法

创建对象时自动调用,用于定义和初始化对象的属性。方法的第一个参数必须是 self(代表当前对象)。

python

class Dog:
    def __init__(self, name, age):
        self.name = name  # 定义属性name
        self.age = age    # 定义属性age
(3)对象的创建

通过类名加括号实例化对象,参数需与 __init__ 方法匹配(无需传入 self)。

python

# 实例化对象
my_dog = Dog("Buddy", 3)
print(my_dog.name)  # 访问对象属性,输出:Buddy

3. 方法的定义

类中定义的函数称为方法,第一个参数必须是 self,其他用法与函数一致。

python

class Dog:
    def __init__(self, name):
        self.name = name
    
    def bark(self):  # 定义方法bark
        print(f"{self.name} is barking!")

my_dog = Dog("Buddy")
my_dog.bark()  # 调用方法,输出:Buddy is barking!

4. 常用魔术方法

魔术方法是 Python 中以双下划线 __ 开头和结尾的特殊方法,用于实现对象的特定行为。

  • __str__:返回对象的字符串表示,便于打印和查看。
    必须返回字符串类型,调用 str(obj) 时自动触发。

    python

    class Dog:
        def __init__(self, name):
            self.name = name
        def __str__(self):
            return f"Dog(name={self.name})"
    
    my_dog = Dog("Buddy")
    print(my_dog)  # 输出:Dog(name=Buddy)
    
  • __eq__:自定义对象的相等性比较(默认比较内存地址)。

    python

    class Dog:
        def __init__(self, name):
            self.name = name
        def __eq__(self, other):
            return self.name == other.name  # 比较名字是否相同
    
    dog1 = Dog("Buddy")
    dog2 = Dog("Buddy")
    print(dog1 == dog2)  # 输出:True(默认情况下为False)
    
  • __del__:对象被销毁时自动调用(析构方法,较少使用)。

5. 属性私有化

为保证数据安全,可将属性或方法私有化,限制外部直接访问。

  • 单下划线 _:受保护的属性 / 方法,仅允许本类和子类使用(君子协议,非强制)。
  • 双下划线 __:私有属性 / 方法,仅允许本类使用。外部需通过 _类名__属性名 访问(不推荐)。
(1)通过 getter 和 setter 访问私有属性

python

class Dog:
    def __init__(self, age):
        self.__age = age  # 私有属性
    
    def get_age(self):  # getter方法
        return self.__age
    
    def set_age(self, new_age):  # setter方法
        if new_age > 0:
            self.__age = new_age

my_dog = Dog(3)
print(my_dog.get_age())  # 输出:3
my_dog.set_age(5)
print(my_dog.get_age())  # 输出:5
(2)property 装饰器(推荐)

简化 getter 和 setter 的调用,使属性访问更自然。

python

class Dog:
    def __init__(self, age):
        self.__age = age
    
    @property
    def age(self):  # 相当于getter
        return self.__age
    
    @age.setter
    def age(self, new_age):  # 相当于setter
        if new_age > 0:
            self.__age = new_age

my_dog = Dog(3)
print(my_dog.age)  # 直接访问,输出:3
my_dog.age = 5     # 直接赋值,输出:5

6. 静态方法与类方法

  • 静态方法:与类和对象均无关,用 @staticmethod 装饰,无需 self 参数。
  • 类方法:与类相关,用 @classmethod 装饰,第一个参数为 cls(代表当前类)。

两者均可通过类直接调用(推荐),也可通过对象调用(不推荐)。

python

class Dog:
    species = "Canine"  # 类属性(所有对象共享)
    
    @staticmethod
    def info():  # 静态方法
        print("Dogs are mammals.")
    
    @classmethod
    def get_species(cls):  # 类方法
        return cls.species

Dog.info()  # 调用静态方法,输出:Dogs are mammals.
print(Dog.get_species())  # 调用类方法,输出:Canine

7. 反射函数

在程序运行时,通过字符串动态操作对象的属性或方法:

  • hasattr(obj, name):判断对象是否有指定属性 / 方法。
  • getattr(obj, name):获取对象的属性 / 方法。
  • setattr(obj, name, value):设置对象的属性。
  • delattr(obj, name):删除对象的属性。

python

class Dog:
    def __init__(self, name):
        self.name = name
    
    def bark(self):
        print("Woof!")

my_dog = Dog("Buddy")
print(hasattr(my_dog, "name"))  # 输出:True
print(getattr(my_dog, "name"))  # 输出:Buddy
setattr(my_dog, "age", 3)       # 动态添加属性age
print(my_dog.age)               # 输出:3

三、继承(Inheritance)

继承允许子类继承父类的属性和方法,实现代码复用和扩展。Python 支持多继承(用逗号分隔多个父类)。

1. 基本用法

python

class Animal:  # 父类
    def __init__(self, name):
        self.name = name
    
    def eat(self):
        print(f"{self.name} is eating.")

class Dog(Animal):  # 子类继承Animal
    def bark(self):
        print(f"{self.name} is barking.")

my_dog = Dog("Buddy")
my_dog.eat()   # 继承父类方法,输出:Buddy is eating.
my_dog.bark()  # 子类自有方法,输出:Buddy is barking.

2. 子类属性初始化

子类初始化时需先初始化父类属性,可通过 super() 调用父类的 __init__ 方法。

python

class Animal:
    def __init__(self, name):
        self.name = name

class Dog(Animal):
    def __init__(self, name, breed):
        super().__init__(name)  # 初始化父类属性
        self.breed = breed     # 子类自有属性

my_dog = Dog("Buddy", "Golden Retriever")
print(my_dog.name, my_dog.breed)  # 输出:Buddy Golden Retriever

3. 方法重写

当父类方法不满足子类需求时,子类可重写父类方法,通过 super() 可调用父类原方法。

python

class Animal:
    def make_sound(self):
        print("Some sound")

class Dog(Animal):
    def make_sound(self):
        super().make_sound()  # 调用父类方法
        print("Woof!")

my_dog = Dog()
my_dog.make_sound()
# 输出:
# Some sound
# Woof!

4. 多继承与方法查找顺序

多继承时,若多个父类有同名方法,Python 会按MRO(方法解析顺序) 查找(从左到右,深度优先)。

python

class A:
    def func(self):
        print("A's func")

class B(A):
    pass

class C(A):
    def func(self):
        print("C's func")

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

d = D()
d.func()  # 输出:C's func(按MRO:D → B → C → A)

5. 抽象类

抽象类是包含抽象方法(仅定义接口,无实现)的类,用于制定标准,且不允许实例化
需继承 abc.ABC 类,并通过 @abc.abstractmethod 装饰抽象方法。子类必须重写所有抽象方法,否则仍为抽象类。

python

import abc

class Animal(abc.ABC):  # 抽象类
    @abc.abstractmethod
    def make_sound(self):  # 抽象方法
        pass  # 无实现

class Dog(Animal):
    def make_sound(self):  # 必须重写
        print("Woof!")

# animal = Animal()  # 报错:无法实例化抽象类
dog = Dog()
dog.make_sound()  # 输出:Woof!

四、多态(Polymorphism)

多态指同一方法通过不同对象调用时表现出不同行为,主要通过方法重写实现。Python 天然支持多态(“鸭子类型”:只要对象有对应方法,即可调用,无需显式继承)。

python

class Dog:
    def make_sound(self):
        print("Woof!")

class Cat:
    def make_sound(self):
        print("Meow!")

def animal_sound(animal):  # 统一接口
    animal.make_sound()

dog = Dog()
cat = Cat()
animal_sound(dog)  # 输出:Woof!
animal_sound(cat)  # 输出:Meow!

五、元类(Metaclass)

元类是类的类,用于控制类的创建过程。所有类的类型都是 type(元类的基类)。

1. 用 type 创建类

type 是 Python 的内置元类,可动态创建类:type(类名, 父类元组, 类属性字典)

python

# 等价于 class MyClass: pass
MyClass = type("MyClass", (), {})
obj = MyClass()

2. 自定义元类

通过继承 type 自定义元类,重写 __new__ 或 __init__ 方法控制类的创建。

python

class MyMeta(type):
    def __new__(cls, name, bases, attrs):
        # 在类创建前修改属性(如添加前缀)
        new_attrs = {f"my_{k}": v for k, v in attrs.items()}
        return super().__new__(cls, name, bases, new_attrs)

class MyClass(metaclass=MyMeta):  # 指定元类
    x = 10

obj = MyClass()
print(obj.my_x)  # 输出:10(属性被自动添加前缀)

总结

面向对象编程通过封装、继承和多态三大特性,实现了代码的模块化、复用性和可维护性,尤其适合复杂系统的开发。理解类与对象的关系、掌握魔术方法、继承机制和多态特性,是灵活运用 OOP 的关键。元类作为进阶概念,可用于深度定制类的行为,进一步拓展 Python 的编程能力。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值