面向对象与面向过程编程:核心区别解析

1.面向过程和面向对象

  • 面向对象编程(OOP)与结构化编程是两种不同的编程范式,它们解决问题的思路有着本质区别:

    结构化编程(面向过程)的特点:

  • 分析阶段:通过自顶向下的方式将问题分解为若干步骤
  • 实现阶段:将每个步骤转化为独立的方法/函数
  • 执行方式:程序通过依次调用这些方法来完成功能
    • 示例:银行转账程序可能包含:
      • validateInput()验证输入
      • checkBalance()检查余额
      • updateAccounts()更新账户
      • logTransaction()记录日志
  • 局限性:数据和方法分离,当系统复杂时维护困难

  • 面向对象编程的特点:

  • 思维方式:将现实世界的事物抽象为具有属性和行为的对象
  • 核心概念:
    • 封装:隐藏对象内部实现细节(如汽车不需要了解发动机原理就能驾驶)
    • 继承:实现代码复用(如"电动车"继承自"汽车"的基本特性)
    • 多态:相同接口不同实现(如不同支付方式的支付操作)

2.面向对象和面向过程的区别 

        面向过程编程(Procedure Oriented Programming,POP)是一种以过程为中心的编程范式。

 

在实现功能时:

  1. 详细分析功能需求,将其拆解为一系列具体的操作步骤
  2. 每个步骤对应一个独立的函数或过程
  3. 通过函数调用的线性组合来实现完整功能
  4. 开发者需要亲自处理每个细节,包括数据结构和算法实现

典型应用场景:

  • 计算器程序:需要逐步实现输入处理、运算执行、结果显示等步骤
  • 文件处理:需要依次完成打开文件、读取数据、处理内容、保存结果等操作
  • 数学运算:如求解方程需要分解为输入系数、计算判别式、求根等步骤

面向对象编程(Object Oriented Programming,OOP)是一种以对象为中心的编程范式。在实现功能时,开发者关注的是:

  1. 识别系统中存在的对象及其属性和行为
  2. 通过创建对象实例来完成任务
  3. 对象之间通过消息传递进行协作
  4. 开发者可以"委托"对象完成工作,而非亲自实现每个细节

 

核心特征:

  • 封装:将数据和操作封装在对象内部
  • 继承:通过继承复用已有类的功能
  • 多态:同一操作在不同对象上有不同表现

实际应用示例:

  • 图形界面开发:按钮、窗口等组件都是对象,开发者只需设置属性,不用关心如何绘制
  • 游戏开发:角色、道具等作为对象,开发者调用对象方法实现交互
  • 企业系统:员工、部门等业务实体作为对象,通过对象协作完成业务流程

两者的本质区别在于: 面向过程是"怎么做"(How)的思维,强调算法和步骤;面向对象是"谁来做"(Who)的思维,强调责任分配和对象协作。面向对象通过封装和抽象,让开发者可以站在更高层次思考问题,将部分工作委托给对象完成。

类和对象:

3.类和对象的概念详解

类(Class):

        类是对一系列具有相同属性和行为的事物的抽象描述,它是一个模板或蓝图,不是真实存在的具体事物。类定义了该类别事物共有的特征和行为。

类的定义格式:

class ClassName:
    """类的文档字符串"""
    class_body

其中:

  • ClassName 是类名,必须符合以下规则:
    • 遵循大驼峰命名法(PascalCase),即每个单词首字母大写,如StudentInfo
    • 不能使用Python关键字
    • 不能包含特殊字符(除下划线外)
    • 尽量做到见名知意,反映类的功能或特性
  • class_body 包含类的属性和方法定义

示例:

class Car:
    """汽车类,描述汽车的基本属性和行为"""
    
    def __init__(self, brand, color):
        self.brand = brand  # 品牌属性
        self.color = color  # 颜色属性
    
    def drive(self):
        """行驶方法"""
        print(f"{self.color}的{self.brand}汽车正在行驶")

对象(Object):

        对象是类的具体实例,是面向对象编程的核心实体。类定义了结构,而对象则是根据这个结构创建的具体实例。

对象实例化:

创建对象的格式:

object_name = ClassName(arguments)

其中:

  • object_name 是对象名,遵循小写字母和下划线的命名惯例
  • ClassName(arguments) 调用类的构造方法创建对象

示例:

my_car = Car("Toyota", "红色")  # 创建一个Car类的实例
your_car = Car("BMW", "黑色")   # 创建另一个Car类的实例

重要注意事项:

  1. 类与对象的关系

    • 必须先定义类,才能创建该类的对象
    • 类是一个抽象概念,对象是类的具体表现
    • 一个类可以创建多个对象实例
  2. 对象独立性

    • 每个对象都是独立的,拥有自己的属性值
    • 修改一个对象的属性不会影响其他对象
  3. 实际应用场景

    • 在游戏开发中,一个"Enemy"类可以创建多个敌人对象
    • 在电商系统中,一个"Product"类可以创建多种商品对象
    • 在社交应用中,一个"User"类可以创建多个用户账号对象

  • 举例如下:
# 2.类和对象
# 类就是对一系列具有相同属性和行为的事物的统称,不是真实存在的事物
# 对象是类的具体表现,是类创建出来的真实存在的事物,是面向对象编程的核心
# 在开发中,先有类,再有对象
# 2.1 类的三要素
# 1.类名
# 2.属性:对象的特征描述,用来说明是什么样子的
# 3.方法:对象具有的功能(行为),用来说明能够做什么
# 举例:
# 类名:植物类
# 属性:叶子、根茎、果实
# 方法:光合作用、吸收水分、开花结果
# 2.2定义类
# 基本格式
# class类名:      # 类名要符合标识符规定,同时遵循大驼峰命名法,见名知意
#   代码块

# 植物类
class Plant:
    leaf = 100    # 类属性:就是类所拥有的属性
print(Plant.leaf)
# 新增类属性:类名.属性名 = 值
Plant.fruit = 50
print(Plant.fruit)

4.创建对象

在面向对象编程中,创建对象是程序运行的基本操作之一。

使用构造函数创建对象:

# 创建对象
# 创建对象的过程也叫做实例化对象
# 2.3.1实例化对象的基本格式:对象名 = 类名()
# 实例化一个植物对象
class Plant:
    leaf = 100
flower1 = Plant()
print(flower1)      # 显示的对象在内存中的地址
# <__main__.Plant object at 0x000002973EF80F80>
# 第二次实例化
flower2 = Plant()
print(flower2)
# <__main__.Plant object at 0x000002973EF80F50>
# 内存地址不一样,说明是不同的对象,可以实例化多个对象

对象创建的注意事项:

  • 内存管理:频繁创建大量对象可能导致内存问题
  • 原型继承:理解原型链对于正确创建对象很重要
  • 性能考量:不同创建方式在性能上可能有差异
  • 对象初始化:确保对象被正确初始化,避免undefined属性

5.实例方法和实例对象详解

实例对象的概念:

实例对象是通过类创建的具体实体,每个实例都拥有独立的属性和方法。例如:

class Dog:
    def __init__(self, name):
        self.name = name  # 实例变量

my_dog = Dog("Buddy")  # 创建Dog类的实例对象
your_dog = Dog("Max")  # 另一个实例对象

实例方法的特点:

  • 定义方式:实例方法第一个参数必须是self,代表当前实例对象
  • 调用方式:必须通过实例对象调用,不能通过类直接调用
  • 访问权限:可以访问和修改实例的所有属性和方法

实例方法的典型应用:

class BankAccount:
    def __init__(self, account_holder, balance=0):
        self.account_holder = account_holder
        self.balance = balance
    
    # 实例方法
    def deposit(self, amount):
        self.balance += amount
        print(f"存入{amount}元,当前余额:{self.balance}")
    
    def withdraw(self, amount):
        if amount > self.balance:
            print("余额不足")
        else:
            self.balance -= amount
            print(f"取出{amount}元,当前余额:{self.balance}")

# 使用实例方法
account = BankAccount("张三", 1000)
account.deposit(500)  # 调用实例方法
account.withdraw(200)

实例方法与类方法的区别:

特性 实例方法 类方法
定义修饰符 @classmethod
第一参数 self (实例对象) cls (类本身)
调用方式 通过实例调用 通过类或实例调用
访问权限 可访问实例属性和类属性 只能访问类属性

实际应用场景:

  • 对象状态修改:如游戏角色的移动、攻击等行为
  • 对象间交互:如社交网络中的用户关注、点赞操作
  • 数据封装:如银行账户的存取款操作封装为实例方法

注意事项:

  • 实例方法不能脱离实例单独存在
  • 不同实例的同名方法互不影响
  • 实例方法可以访问类级别的属性和方法
  • 在继承体系中,子类可以重写父类的实例方法

6.实例属性和类属性的区别详解

基本概念:

实例属性是绑定到某个特定对象实例上的属性,每个实例可以拥有不同的属性值。实例属性通常在类的__init__方法中定义,使用self关键字进行绑定。

类属性是直接绑定到类本身的属性,所有实例共享同一个类属性值。类属性在类定义中直接声明,位于任何方法之外。

核心区别:

  • 存储位置不同

    • 实例属性存储在单个实例的__dict__
    • 类属性存储在类的__dict__
  • 访问方式不同

    • 实例属性:instance.attribute
    • 类属性:Class.attributeinstance.attribute(当实例没有同名属性时)
  • 修改影响范围不同

    • 修改实例属性只影响当前实例
    • 修改类属性会影响所有实例(除非实例已创建同名实例属性)

代码示例:

class Dog:
    # 类属性
    species = "Canis familiaris"
    
    def __init__(self, name, age):
        # 实例属性
        self.name = name
        self.age = age

# 创建实例
buddy = Dog("Buddy", 5)
miles = Dog("Miles", 3)

# 访问类属性
print(buddy.species)  # Canis familiaris
print(Dog.species)    # Canis familiaris

# 修改实例属性
buddy.age = 6

# 修改类属性
Dog.species = "Canis lupus"  # 影响所有实例

使用场景:

适合使用类属性的情况:

  • 用于存储所有实例共享的常量值
  • 用于统计实例数量(如count = 0)
  • 用于定义默认值
  • 适合使用实例属性的情况:

  • 需要为每个实例存储独特数据时
  • 属性值需要在实例生命周期中变化时
  • 需要隔离不同实例的状态时

注意事项:

  • 属性查找顺序:Python会先查找实例属性,如果没有找到才会查找类属性
  • 可变类属性:当类属性是可变对象(如列表)时,修改它会影响所有实例
  • 动态添加属性:可以在运行时动态添加类属性和实例属性

7.构造函数

基本概念:

        构造函数(Constructor)是一种特殊的类成员函数,它在创建类对象时自动调用,主要用于初始化对象的状态。构造函数具有以下特点:

  1. 名称与类名完全相同
  2. 没有返回类型(连void也没有)
  3. 可以重载(一个类可以有多个不同参数的构造函数)
  4. 通常声明为public访问权限(除非有特殊需求)

构造函数的类型:

默认构造函数:

        当类没有定义任何构造函数时,编译器会自动生成一个无参数的默认构造函数。默认构造函数会:

  • 为基本类型成员变量赋予默认值(如int为0,指针为nullptr等)
  • 调用类类型成员变量的默认构造函数

应用场景:

# 3.构造函数__init__
# 作用:通常同来做属性初始化或者赋值操作
# 注意:在类实例化对象的时候,会被自动调用
class Tset:
    def __init__(self):  # self--实例方法
        print("这是__init__()函数")
# 实例化对象:对象名 = 类名()
# li = Tset()
class Person:   # 人
    def __init__(self,name,age,hight):
        self.name = name     # 实例属性  姓名
        self.age = age           # 年龄
        self.hight = hight        # 身高
    def play(self):
        print(f"{self.name}在砍巨人")
    def introduce(self):
        print(f"{self.name}的年龄是{self.age},身高是{self.hight}cm")
# 实例化对象
li = Person('三笠',18,173)
li.play()
li.introduce()
# 实例化第二个对象
li2 = Person('艾伦',19,175)
li2.play()
li2.introduce()
# 实例化第三次
li3 = Person('尤米尔',15,166)
li3.play()
li3.introduce()

注意事项:

  1. 构造函数不应抛出异常(如果可能抛出,应考虑使用工厂模式)
  2. 构造函数中应避免调用虚函数(此时对象的虚表可能尚未完全初始化)
  3. 对于包含const成员或引用成员的类,必须使用初始化列表
  4. 当类有虚函数时,应定义虚析构函数

8.析构函数:

        __del__方法: 析构方法__del__是Python中一个重要的特殊方法,它在对象生命周期结束时被自动调用。

        当对象的引用计数降为0,或者垃圾回收器决定回收该对象时,__del__方法就会被执行。

        该方法的主要作用是进行资源清理工作,如关闭文件、释放网络连接等。

        具体来说:当没有任何变量引用该对象时,Python的垃圾回收机制会自动调用__del__方法该方法通常用于清理对象占用的非内存资源调用时机不确定,不建议依赖该方法进行关键资源清理

 

示例场景:

def __del__(self):
    self.file.close()
    print("文件资源已释放")
# 析构函数 __del__()
# 删除对象的时候,解释器会默认调用__del__()方法
class Person:
    def __init__(self):
        print("我是__init__()")
    def __del__(self):
        print("被销毁了")
li = Person()
del li # 删除li这个对象
# del li 语句执行的时候,内存会立即被回收,会调用对象本身的__del__()方法
print("这是最后两行代码")
print("这是最后一行代码")
# 正常运行时,不会调用__del__(),对象执行结束之后,系统会自动调用__del__()
# __del__()主要是表示程序块或者函数已经全部执行结束

注意事项:

        __del__方法的调用时机由Python解释器决定 在循环引用的情况下,对象可能不会被立即回收 更好的做法是显式调用close()等方法进行资源管理 不建议在__del__中执行耗时操作或启动新线程

9.封装与继承

封装:

        封装是指将复杂的信息、流程和实现细节隐藏在内部,对外仅暴露简单的接口,让使用者无需了解内部实现就能方便地使用功能。就像使用微波炉时,我们只需要设置时间和功率,而不需要知道微波是如何产生的。

封装的主要特点:

  1. 信息隐藏:将对象的属性和实现细节隐藏在内部
  2. 接口简化:对外提供简单易用的操作方式
  3. 安全性:通过访问控制保护关键数据不被随意修改

 

编程中的封装实现:

# 封装
# 面向对象的三大特性:封装、继承、多态
# 封装:指的是隐藏对象中一些不希望被外部访问到的属性或者方法
class Person:
    name = '三笠'  # 类属性
li = Person()
print(li.name)
Person.name = '艾伦'
print(Person.name)

 

继承:

        继承是面向对象编程的重要特性,它允许新创建的类(子类)获得已有类(父类)的属性和方法,并可以在此基础上进行扩展或修改。

继承的主要特点:

  • 代码复用:子类自动获得父类的功能
  • 扩展性:可以在不修改父类的情况下添加新功能
  • 层次结构:可以建立类与类之间的层级关系
  • 封装的实际应用示例:

  • 汽车驾驶:驾驶员只需要操作方向盘、油门和刹车,不需要了解发动机如何工作
  • ATM取款:用户只需要输入密码和金额,银行系统内部处理所有的账户验证和资金转账
  • 智能手机:用户通过触摸屏操作,不需要知道应用程序如何与硬件交互

10.私有属性/方法详解

普通变量/方法 (xxx):

普通变量和方法是最基础的类型,完全公开可访问。例如:

class MyClass:
    def public_method(self):
        print("这是一个公开方法")
    
    value = 10  # 公开属性

私有属性/方法 (_xxx):

用一个下划线前缀表示私有属性/方法,这是一种约定俗成的做法(PEP8规范),表示仅供内部使用:

class MyClass:
    def _private_method(self):
        print("这是一个私有方法,不建议外部调用")
    
    _internal_value = 20  # 私有属性
    
    def public_api(self):
        # 在类内部可以调用私有方法
        self._private_method()
        return self._internal_value

注意:

  • 仍可以从外部访问,只是表明"不建议直接使用"
  • 导入时 from module import * 不会导入 _xxx 名称
  • 常用于子类继承时使用的"保护"成员

隐藏属性 (__xxx):

双下划线前缀会触发Python的名称改写(name mangling),提供更强的隔离性:

class MyClass:
    def __very_private_method(self):
        print("这个方法的名称会被改写")
    
    __secret_value = 30
    
    def access_hidden(self):
        # 在类内部仍可用原名访问
        self.__very_private_method()
        return self.__secret_value

特性:

  • 实际会被改写为 _ClassName__xxx 的形式
  • 主要用于避免子类中的命名冲突
  • 仍可通过改写后的名称访问,但强烈不建议
  • 常用于实现框架内部机制

魔法方法 (xxx):

双下划线包围的是Python的特殊方法:

class MyClass:
    def __init__(self):  # 构造方法
        pass
    
    def __str__(self):  # 字符串表示
        return "MyClass instance"

注意:

  • 这些都是Python预定义的
  • 除非要实现特定协议,否则不要自行创建
  • 例如 __len__, __getitem__

 

你可能感兴趣的:(Python,python,开发语言)