Python类与对象篇(七)

面向对象编程

Python 的面向对象编程(Object-Oriented Programming, OOP)是一种编程风格,它将数据(属性)和功能(方法)封装在称为类(class)的结构中。这样做的主要目的是为了提高代码的可重用性、可维护性和可扩展性。

在 Python 中,面向对象编程主要包含以下几个核心概念:

  • 类(Class): 类是对象的蓝图或模板,定义了对象的属性(数据)和方法(功能)。
  • 对象(Object): 类的实例化,是一个具有类定义的属性和方法的具体实体。
  • 继承(Inheritance): 子类继承父类的属性和方法,可以扩展或重写父类的功能。
  • 多态(Polymorphism): 不同类的对象对同一消息做出不同的响应。
  • 封装(Encapsulation): 将数据和方法绑定在一起,并通过访问控制保护对象的内部状态。

类与对象

类是一个蓝图或模板,用于定义对象的属性(数据)和方法(行为)。通过类,你可以创建具有相同属性和行为的多个对象。

类的定义
在Python中,使用 class 关键字定义一个类。类通常包含两个主要部分:

  • 属性:类中的变量,通常用于存储对象的状态或数据。
  • 方法:类中的函数,通常用于定义对象的行为或操作

对象是类的实例化,即根据类创建的具体实体。每个对象都有自己独立的属性值,但共享同一个类定义的结构和方法

类的属性与方法

class Dog:
    # 类属性
    species = "Canis familiaris"

    # 初始化方法,创建实例时自动调用
    def __init__(self, name, age):
        # 实例属性
        self.name = name
        self.age = age

    # 实例方法
    def bark(self):
        return f"{self.name} 说:汪汪!"

    # 实例方法
    def get_age(self):
        return f"{self.name}{self.age} 岁。"

在这个例子中,Dog 类定义了一个狗的模板,包含了属性 name 和 age,以及方法 bark 和 get_age。

进一步理解

  • 封装:类将数据和操作封装在一起,使得代码更清晰、更易维护。
  • 继承:可以创建一个新类,它继承(复用)已有类的属性和方法,同时可以扩展或修改。
  • 多态:对象可以通过同样的接口调用不同类的实现,从而实现灵活的代码设计。

案例理解
创建一个简单的银行账户系统,这个系统允许用户创建账户、存款、取款,并查询余额

定义一个 BankAccount 类,这个类将作为银行账户的模板。它将包含账户持有人的名字、账户余额,以及一些用于操作账户的功能(如存款和取款)

class BankAccount:
    # 初始化方法,用于创建新账户时设定初始值
    def __init__(self, owner, balance=0):
        self.owner = owner  # 账户持有人
        self.balance = balance  # 账户余额,默认为0

    # 方法:显示账户信息
    def display_account_info(self):
        return f"账户持有人: {self.owner}, 账户余额: {self.balance} 元"

    # 方法:存款
    def deposit(self, amount):
        if amount > 0:
            self.balance += amount
            print(f"{amount} 元已存入账户。新余额: {self.balance} 元")
        else:
            print("存款金额必须大于0元。")

    # 方法:取款
    def withdraw(self, amount):
        if 0 < amount <= self.balance:
            self.balance -= amount
            print(f"{amount} 元已从账户中取出。新余额: {self.balance} 元")
        else:
            print("取款金额无效或余额不足。")

使用 BankAccount 类来创建两个银行账户对象,并对其进行操作

# 创建两个银行账户对象
account_1 = BankAccount("张三", 1000)
account_2 = BankAccount("李四", 500)

# 显示账户信息
print(account_1.display_account_info())  # 输出: 账户持有人: 张三, 账户余额: 1000 元
print(account_2.display_account_info())  # 输出: 账户持有人: 李四, 账户余额: 500 元

# 对账户进行存款和取款操作
account_1.deposit(500)  # 张三存款500元
account_1.withdraw(300)  # 张三取款300元

account_2.deposit(200)  # 李四存款200元
account_2.withdraw(800)  # 李四试图取款800元,失败因为余额不足

运行结果

账户持有人: 张三, 账户余额: 1000 元
账户持有人: 李四, 账户余额: 500500 元已存入账户。新余额: 1500300 元已从账户中取出。新余额: 1200200 元已存入账户。新余额: 700 元
取款金额无效或余额不足。

构造函数与析构函数

在Python中,构造函数和析构函数是与类(Class)相关的特殊方法,用于在对象创建和销毁时执行特定操作。在对象的生命周期内管理资源和初始化属性。

构造函数(Constructor)
构造函数是在创建对象时自动调用的方法,用于初始化对象的状态或属性。在Python中,构造函数由一个特殊的方法 init() 表示。

特点:

  • 构造函数的主要作用是设置对象的初始状态,即为对象的属性赋初值。
  • 当你创建一个类的实例时,Python会自动调用 init() 方法,不需要你显式调用它。
class Person:
    # 构造函数
    def __init__(self, name, age):
        self.name = name  # 初始化name属性
        self.age = age  # 初始化age属性

    def greet(self):
        print(f"大家好,我是 {self.name},今年 {self.age} 岁。")

# 创建对象时自动调用构造函数
person_1 = Person("张三", 30)
person_1.greet()  # 输出: 大家好,我是 张三,今年 30 岁。

在这个例子中,init() 是 Person 类的构造函数,用于在创建 Person 对象时初始化 name 和 age 属性

析构函数(Destructor)
析构函数是在对象被销毁(即不再被使用)时自动调用的方法,用于清理资源或执行其他必要的清理操作。在Python中,析构函数由一个特殊的方法 del() 表示。

特点:

  • 析构函数的主要作用是在对象生命周期结束时执行清理操作,如关闭文件、释放资源等。
  • 当一个对象不再被引用(即它的引用计数变为0)时,Python的垃圾收集器会调用 del() 方法销毁对象。
class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age
        print(f"{self.name} 对象已创建")

    def greet(self):
        print(f"大家好,我是 {self.name},今年 {self.age} 岁。")

    # 析构函数
    def __del__(self):
        print(f"{self.name} 对象已销毁")

# 创建对象
person_1 = Person("张三", 30)
person_1.greet()  # 输出: 大家好,我是 张三,今年 30 岁。

# 删除对象
del person_1  # 手动销毁对象,调用析构函数

在这个例子中,del() 是 Person 类的析构函数,用于在对象被销毁时输出一条消息。你可以手动销毁对象,也可以让Python的垃圾回收器自动处理。

总结

  • 构造函数 (init):在对象创建时自动调用,用于初始化对象的属性和状态。
  • 析构函数 (del):在对象销毁时自动调用,用于清理资源或执行其他必要的清理操作。

继承与多态

继承(Inheritance)
继承允许你创建一个新的类,这个类可以继承(复用)另一个类的属性和方法。被继承的类称为父类或基类,新创建的类称为子类或派生类。

继承的特点:

  • 代码重用:子类可以直接使用父类中定义的属性和方法,而无需重新编写。
  • 扩展性:子类可以添加新的属性和方法,或者重写父类的方法来实现不同的行为。
# 定义父类
class Animal:
    def __init__(self, name):
        self.name = name

    def speak(self):
        return f"{self.name} 发出声音。"

# 定义子类,继承自 Animal
class Dog(Animal):
    def __init__(self, name, breed):
        # 调用父类的构造函数
        super().__init__(name)
        self.breed = breed

    # 重写父类的 speak 方法
    def speak(self):
        return f"{self.name} 说:汪汪!"

# 定义另一个子类
class Cat(Animal):
    def speak(self):
        return f"{self.name} 说:喵喵!"

# 创建对象
dog = Dog("Buddy", "Golden Retriever")
cat = Cat("Whiskers")

print(dog.speak())  # 输出: Buddy 说:汪汪!
print(cat.speak())  # 输出: Whiskers 说:喵喵!

多态(Polymorphism)
多态指的是“同一接口,不同实现”的能力。换句话说,不同的子类可以以各自特定的方式实现父类的相同方法。当你通过父类引用调用这个方法时,它会自动选择正确的子类实现。

多态的特点:

  • 接口统一:多态使得子类可以通过相同的接口(方法名)实现不同的行为。
  • 灵活性和扩展性:通过多态,程序可以在不修改代码的前提下,轻松扩展新的子类和新的行为。
# 使用前面的类定义

# 定义一个函数,接受任意 Animal 对象,并调用 speak 方法
def animal_sound(animal):
    print(animal.speak())

# 调用函数时,传入不同的子类对象
animal_sound(dog)  # 输出: Buddy 说:汪汪!
animal_sound(cat)  # 输出: Whiskers 说:喵喵!

继承与多态的结合
继承和多态通常是结合使用的。继承提供了代码复用的机制,而多态提供了扩展和灵活性。

封装与私有属性

封装和私有属性是面向对象编程中的两个重要概念,它们帮助你保护对象的内部状态,并控制对其的访问。

封装(Encapsulation)
*封装是指将对象的属性(数据)和方法(行为)封装在一起,使它们成为一个独立的单元。在 Python中,通过封装,你可以隐藏对象的内部实现细节,暴露出简洁的接口(方法),供外部使用。

封装的特点:

  • 数据保护:通过封装,你可以保护对象的内部状态,不让外部随意修改。
  • 简化接口:只向外部暴露必要的方法,隐藏复杂的内部实现。
  • 提高代码维护性:内部实现的变化不会影响外部代码。
class Employee:
    def __init__(self, name, salary):
        self.name = name  # 公有属性
        self.__salary = salary  # 私有属性(用两个下划线前缀)

    # 公有方法,外部可访问
    def get_info(self):
        return f"员工姓名: {self.name}, 薪水: {self.__salary} 元"

    # 私有方法,外部不可直接访问
    def __calculate_tax(self):
        return self.__salary * 0.2

    # 提供一个公有方法访问私有方法
    def get_tax(self):
        return f"{self.name} 的应缴税款: {self.__calculate_tax()} 元"

在这个例子中,Employee 类封装了员工的姓名和薪水,并提供了公有方法 get_info() 和 get_tax(),供外部访问。这些方法隐藏了内部计算税款的逻辑,只暴露必要的信息

私有属性(Private Attributes)
私有属性是指只能在类的内部访问的属性。在Python中,使用两个下划线前缀(如 __attribute)将属性声明为私有。私有属性不能在类外部直接访问,这样可以防止外部代码意外或恶意地修改对象的内部状态。

私有属性的特点:

  • 只能在类内部访问:私有属性不能在类外部直接访问或修改。
  • 保护对象的内部状态:防止外部代码破坏对象的一致性或安全性。
# 使用前面的 Employee 类定义

# 创建对象
emp = Employee("李四", 5000)

# 访问公有属性
print(emp.name)  # 输出: 李四

# 试图访问私有属性(会导致错误)
# print(emp.__salary)  # 这行代码会报错:AttributeError

# 正确访问私有属性的方法是通过类的公有方法
print(emp.get_info())  # 输出: 员工姓名: 李四, 薪水: 5000 元

# 访问私有方法计算税款
print(emp.get_tax())  # 输出: 李四 的应缴税款: 1000.0 元

在这个例子中,__salary 是私有属性,无法在类外部直接访问,但可以通过公有方法 get_info() 和 get_tax() 来间接访问和操作

小结

  • 封装是一种将对象的属性和方法封装在一起的技术,通过限制对某些属性和方法的访问,保护对象的内部状态,简化外部接口。
  • 私有属性是封装的实现手段之一,使用两个下划线前缀将属性设为私有,防止外部直接访问。

使用封装和私有属性的好处:

  • 安全性:保护对象的内部数据,防止被外部代码篡改。
    灵活性:可以随时修改对象的内部实现,而不影响外部代码。
    易于维护:通过清晰的接口,减少外部代码与内部实现的耦合,使得代码更易维护和扩展
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

huhy~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值