Python类与对象篇(七)

embedded/2024/9/24 5:09:49/

python

    • 面向对象编程
      • 类与对象
      • 类的属性与方法
      • 构造函数与析构函数
      • 继承与多态
      • 封装与私有属性

面向对象编程

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

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

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

类与对象

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

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

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

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

类的属性与方法

python">class Dog:# 类属性species = "Canis familiaris"# 初始化方法,创建实例时自动调用def __init__(self, name, age):# 实例属性self.name = nameself.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 类,这个类将作为银行账户的模板。它将包含账户持有人的名字、账户余额,以及一些用于操作账户的功能(如存款和取款)

python">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 += amountprint(f"{amount} 元已存入账户。新余额: {self.balance} 元")else:print("存款金额必须大于0元。")# 方法:取款def withdraw(self, amount):if 0 < amount <= self.balance:self.balance -= amountprint(f"{amount} 元已从账户中取出。新余额: {self.balance} 元")else:print("取款金额无效或余额不足。")

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

python"># 创建两个银行账户对象
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元,失败因为余额不足

运行结果

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

构造函数与析构函数

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

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

特点:

  • 构造函数的主要作用是设置对象的初始状态,即为对象的属性赋初值。
  • 当你创建一个类的实例时,Python会自动调用 init() 方法,不需要你显式调用它。
python">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() 方法销毁对象。
python">class Person:def __init__(self, name, age):self.name = nameself.age = ageprint(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)
继承允许你创建一个新的类,这个类可以继承(复用)另一个类的属性和方法。被继承的类称为父类或基类,新创建的类称为子类或派生类。

继承的特点:

  • 代码重用:子类可以直接使用父类中定义的属性和方法,而无需重新编写。
  • 扩展性:子类可以添加新的属性和方法,或者重写父类的方法来实现不同的行为。
python"># 定义父类
class Animal:def __init__(self, name):self.name = namedef 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)
多态指的是“同一接口,不同实现”的能力。换句话说,不同的子类可以以各自特定的方式实现父类的相同方法。当你通过父类引用调用这个方法时,它会自动选择正确的子类实现。

多态的特点:

  • 接口统一:多态使得子类可以通过相同的接口(方法名)实现不同的行为。
  • 灵活性和扩展性:通过多态,程序可以在不修改代码的前提下,轻松扩展新的子类和新的行为。
python"># 使用前面的类定义# 定义一个函数,接受任意 Animal 对象,并调用 speak 方法
def animal_sound(animal):print(animal.speak())# 调用函数时,传入不同的子类对象
animal_sound(dog)  # 输出: Buddy 说:汪汪!
animal_sound(cat)  # 输出: Whiskers 说:喵喵!

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

封装与私有属性

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

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

封装的特点:

  • 数据保护:通过封装,你可以保护对象的内部状态,不让外部随意修改。
  • 简化接口:只向外部暴露必要的方法,隐藏复杂的内部实现。
  • 提高代码维护性:内部实现的变化不会影响外部代码。
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)将属性声明为私有。私有属性不能在类外部直接访问,这样可以防止外部代码意外或恶意地修改对象的内部状态。

私有属性的特点:

  • 只能在类内部访问:私有属性不能在类外部直接访问或修改。
  • 保护对象的内部状态:防止外部代码破坏对象的一致性或安全性。
python"># 使用前面的 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() 来间接访问和操作

小结

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

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

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

http://www.ppmy.cn/embedded/100820.html

相关文章

RongCallKit iOS 端本地私有 pod 方案

RongCallKit iOS 端本地私有 pod 方案 需求背景 适用于源码集成 CallKit 时&#xff0c;使用 pod 管理 RTC framework 以及源码。集成 CallKit 时&#xff0c;需要定制化修改 CallKit 的样式以及部分 UI 功能。适用于 CallKit 源码 Debug 调试便于定位相关问题。 解决方案 从…

【RabbitMQ】高级特性

本文将介绍一些RabbitMQ的重要特性。 官方文档&#xff1a;Protocol Extensions | RabbitMQ 本文是使用的Spring整合RabbitMQ环境。 生产者发送确认(publish confirm) 当消息发送给消息队列&#xff0c;如何确保消息队列一定收到消息呢&#xff0c;RabbitMQ通过 事务机制 和 …

spring揭秘09-aop03-aop织入器织入横切逻辑与自动织入

文章目录 【README】【1】spring aop的织入【1.1】使用ProxyFactory 作为织入器【1.2】基于接口的代理&#xff08;JDK动态代理&#xff0c;目标类实现接口&#xff09;【补充】 【1.2】基于类的代理&#xff08;CGLIB动态代理&#xff0c;目标类没有实现接口&#xff09;【1.2…

河南萌新2024第五场

A 日历游戏 题目大意&#xff1a; alice&#xff0c;bob玩游戏&#xff0c;给定一个2000.1.1到2024.8.1之间的任意一个日期&#xff0c;每次进行一次操作&#xff08;保证合法日期&#xff09; 天数1&#xff0c;例如2000.1.1 -> 2000.1.2 月份1&#xff0c;例如2000.1.…

极速文件预览!轻松部署 kkFileView 于 Docker 中!

大家好&#xff0c;这几天闲的难受&#xff0c;决定给自己找点事做。博主的项目中有个文件预览的小需求&#xff0c;原有方案是想将文件转换成 PDF 进行预览。本着能借鉴就绝对不自己写的原则。今天就让我们简单试用一下 kkFileView 文件预览服务&#xff0c;一起探索它的强大功…

【非常困难】 猿人学web第一届 第10题 js 混淆 - 重放攻击对抗

文章目录 调试干扰第一个 debuggerHook 代码 第二个 debuggerHook 代码 第三个 Function.constructor.prototype 检测Hook 代码 完整的 Hook 代码 接口分析加密参数 m 生成位置加密参数还原加密点扣代码提示_yrxyA\$()var _yrxmEu _yrxWKg(_yrxyHJ...._yrxWKg() let result _…

重装后的电脑怎么分区?轻松优化存储空间

电脑重装系统是解决许多软件问题和提升性能的有效方法。然而&#xff0c;重装系统后&#xff0c;合理的硬盘分区不仅能提高数据管理效率&#xff0c;还有助于保护系统安全。本文将详细介绍如何在重装电脑后进行合理的分区&#xff0c;帮助您更好地管理和使用您的电脑。 一、了解…

【C++从小白到大牛】C++智能指针的使用、原理和分类

目录 1、我们为什么需要智能指针&#xff1f; 2、内存泄露 2.1 什么是内存泄漏&#xff0c;内存泄漏的危害 2.2如何避免内存泄漏 总结一下: 3.智能指针的使用及原理 3.1 RAII 3.2关于深拷贝和浅拷贝更深层次的理解&#xff1a; 3.3 std::auto_ptr 3.4 std::unique_pt…