Python 中的类与面向对象编程(二)

目录

一、面向对象编程(OOP)

二、类与实例

1. 类

2. 实例

三、' self ' 关键字

四、魔法函数

1. 初始化与字符串表示

2. 长度与比较

3. 算术运算

五、构造函数与析构函数

1. 初始化函数

2. 构造函数

3. 析构函数

 六、面向对象编程的三大特性

1. 封装

2. 继承

多重继承

3. 多态

1. 方法重载(函数同名不同参数)

2. 父子类多态

七、抽象类

八、动态添加内容

1. 添加实例属性

2. 添加实例方法

3. 添加类属性和方法

九、总结


大家好!今天我们将继续探讨 Python 中的类及其在面向对象编程(OOP)中的应用。面向对象编程是一种编程范式,它使用“对象”来模拟现实世界的事务,使代码更加结构化和易于维护。在上一篇文章中,我们详细了解类和实例的概念、' self ' 关键字的作用、魔法函数的定义、构造函数和析构函数的用途,今天我们会在上一篇文章的基础上补充面向对象编程的三大特性:封装、继承和多态。让我们开始吧!

一、面向对象编程(OOP)

面向对象编程是一种将现实世界事务使用类与实例来模拟的方法。在 OOP 中,所有事物都被视为对象。这些对象可以是具体的,如:

灯:可以开关的设备。
汽车:具有属性(如颜色、品牌)和行为(如行驶、停车)的交通工具。
导弹:具备特定属性和发射行为的武器。
杯子:用于盛放液体的容器。

通过将这些现实世界的事务抽象为对象,我们可以创建更易于理解和操作的代码结构。

二、类与实例

1. 类

类是对现实世界描述的一种类型。它是一个抽象的概念,约定了未来实例应该有的内容。定义类的基本语法如下:

class 类名:pass

在 Python 中,类名通常采用大驼峰(Pascal Case)命名法。例如,我们可以定义一个名为' Car '  的类:

class Car:pass

类是实例的模板,它定义了实例的属性和行为,但并不包含具体的数据。

2. 实例

实例是通过调用类生成的具体对象。生成实例的语法为:

实例名 = 类名()

例如:

my_car = Car()

这里,' my_car ' 是  ' Car ' 类的一个实例,它包含了  ' Car ' 类定义的所有属性和方法,但具体的数据是属于这个实例的。

三、' self ' 关键字

' self ' 关键字在类的方法内部,' self ' 代表实例本身。它用于访问实例的属性和方法。' self ' 必须作为第一个参数出现在类的方法中。让我们看一个简单的例子,展示如何使用 ' self ' :

class Dog:def __init__(self, name):self.name = name  # 将实例属性name初始化为传入的name参数def bark(self):return f"{self.name} says Woof!"

在上面的代码中,' __init__ ' 是一个初始化函数,用于创建实例时初始化属性。通过 ' self ' ,我们可以在 ' bark ' 方法中引用实例的 ' name ' 属性。

四、魔法函数

魔法函数是以双下划线开头和结尾的特殊方法,它们能够实现某些特定的功能。常用的魔法函数包括:

1. 初始化与字符串表示

 ' __init__(self) ' :构造函数,用于初始化实例。
 ' __str__(self) ' :定义对象的字符串表示,通常用于 ' print() ' 函数。

class Cat:def __init__(self, name):self.name = namedef __str__(self):return f"This is {self.name} the cat."
2. 长度与比较

' __len__(self) ' :返回对象的长度。
  
比较运算符魔法函数:' __eq__(self, other) ':等于比较。
' __ne__(self, other) ':不等于比较。
' __gt__(self, other) ':大于比较。
' __ge__(self, other) ':大于或等于比较。
' __lt__(self, other) ':小于比较。
' __le__(self, other) ':小于或等于比较。

class Box:def __init__(self, size):self.size = sizedef __len__(self):return self.sizedef __eq__(self, other):return self.size == other.size
3. 算术运算

魔法函数还可以重载算术运算符,使得我们能够使用常见的运算符(如 `+`、`-` 等)对自定义对象进行操作。这些魔法函数包括:

' __add__(self, other) ' :实现加法运算。
' __sub__(self, other) ':实现减法运算。
' __mul__(self, other) ':实现乘法运算。
' __truediv__(self, other) ':实现除法运算。
' __mod__(self, other) ':实现取模运算。以下是一个示例,展示如何使用 ' __add__ ' 魔法函数:

class Point:def __init__(self, x, y):self.x = xself.y = ydef __add__(self, other):return Point(self.x + other.x, self.y + other.y)def __repr__(self):return f"Point({self.x}, {self.y})"# 创建两个 Point 实例
p1 = Point(1, 2)
p2 = Point(3, 4)
p3 = p1 + p2  # 这里会调用 p1.__add__(p2)
print(p3)  # 输出: Point(4, 6)

在这个例子中,' __add__ ' 方法允许我们直接使用 ' + ' 运算符来相加两个 ' Point ' 实例。

五、构造函数与析构函数

1. 初始化函数

初始化函数是一个特殊的方法,用于初始化实例的属性。' __init__ ' 方法在创建对象时自动调用。

class Person:def __init__(self, name, age):self.name = nameself.age = agedef display(self):return f"姓名: {self.name}, 年龄: {self.age}"# 创建实例
person = Person("Alice", 30)
print(person.display())  # 输出: 姓名: Alice, 年龄: 30

2. 构造函数

构造函数是一个特殊的方法,用于创建实例。' __new__ ' 方法在实例被创建时被调用。通常情况下,我们不需要直接使用 ' __new__ ' ,但在需要控制实例创建过程时可以使用。

class Singleton:_instance = Nonedef __new__(cls):if cls._instance is None:cls._instance = super(Singleton, cls).__new__(cls)return cls._instance# 测试 Singleton 类
s1 = Singleton()
s2 = Singleton()print(s1 is s2)  # 输出: True,确保只有一个实例

3. 析构函数

析构函数是另一个特殊的方法,在实例不再使用时被调用,通常用于释放资源。Python 中的析构函数是 ' __del__ ' 方法。虽然 Python 有垃圾回收机制,但在某些情况下,手动释放资源是很有用的。

析构函数的基本结构如下:

def __del__(self):# 清理代码

下面是一个简单的示例,展示如何使用析构函数:

class Resource:def __init__(self):print("Resource acquired!")def __del__(self):print("Resource released!")# 创建一个资源对象
res = Resource()
# 资源会在对象销毁时被释放

当 ' res ' 对象超出作用域时,Python 的垃圾回收会调用 ' __del__ ' 方法,输出“Resource released!”。

 六、面向对象编程的三大特性

在 OOP 中,有三大基本特性:封装、继承和多态。

1. 封装

封装是指将数据和方法结合在一起,并限制对某些数据的直接访问。通过封装,我们可以保护对象的内部状态,只通过公共方法(接口)来访问和修改这些状态。

class Person:def __init__(self, name, age):self.__name = name  # 私有属性self.__age = age    # 私有属性def get_name(self):return self.__namedef set_name(self, name):self.__name = namedef get_age(self):return self.__agedef set_age(self, age):if age > 0:self.__age = ageelse:print("年龄必须为正数!")# 创建实例
person = Person("Alice", 30)
print(person.get_name())  # 输出: Alice
person.set_age(-5)        # 输出: 年龄必须为正数!

在上面的代码中,我们使用了双下划线 ' __ ' 将实例属性  ' __name '  和 ' __age ' 定义为私有属性,这样它们就不能被直接访问。我们提供了公共方法 ' get_name ' 和  ' set_name ' 来访问和修改这些私有属性。这种封装机制不仅保护了对象的内部状态,还提供了更好的数据验证和控制。

2. 继承

继承是指一个类(子类)可以继承另一个类(父类)的属性和方法,从而实现代码的重用。子类可以扩展或修改父类的行为。

class Animal:def speak(self):return "Animal speaks"class Dog(Animal):  # Dog 继承自 Animaldef speak(self):return "Woof!"class Cat(Animal):  # Cat 也继承自 Animaldef speak(self):return "Meow!"# 实例化对象
dog = Dog()
cat = Cat()
print(dog.speak())  # 输出: Woof!
print(cat.speak())  # 输出: Meow!

在这个例子中,' Dog ' 和 ' Cat ' 类都继承了 ' Animal ' 类的 ' speak ' 方法,但它们各自实现了自己的版本。这种特性使得我们可以创建一个通用的父类,并根据需要扩展子类。

多重继承

Python 支持多重继承,即一个类可以同时继承多个类。这在某些情况下非常有用,但也可能导致复杂性(如菱形继承问题)。

class Flyer:def fly(self):return "Flying"class Swimmer:def swim(self):return "Swimming"class Duck(Flyer, Swimmer):def quack(self):return "Quack!"# 实例化 Duck
duck = Duck()
print(duck.fly())  # 输出: Flying
print(duck.swim())  # 输出: Swimming
print(duck.quack())  # 输出: Quack!

3. 多态

多态是指不同类的对象可以通过相同的接口进行操作。多态的实现通常依赖于继承和方法重载。Python 中的多态通常有两种形式:

1. 方法重载(函数同名不同参数)

Python 不支持传统意义上的方法重载,但我们可以使用可变参数( ' *args ' 和 ' **kwargs ' )来实现类似效果。

class MathOperation:def add(self, *args):return sum(args)math_op = MathOperation()
print(math_op.add(1, 2))          # 输出: 3
print(math_op.add(1, 2, 3, 4, 5))  # 输出: 15
2. 父子类多态

父类和子类的方法名相同,但实现不同。我们可以通过多态来处理不同类型的对象。

def animal_sound(animal):print(animal.speak())# 实例化对象
dog = Dog()
cat = Cat()
animal_sound(dog)  # 输出: Woof!
animal_sound(cat)  # 输出: Meow!

在这个例子中,' animal_sound ' 函数接收 ' Animal ' 类型的对象,不论是 ' Dog ' 还是 ' Cat ',都可以调用 ' speak ' 方法。

七、抽象类

抽象类是一种特殊的类,用于定义接口和强制子类实现特定的方法。抽象类不能被实例化,通常用于提供一个模板,要求其子类实现抽象方法。使用 ' abc ' 模块来定义抽象类和抽象方法。

from abc import ABC, abstractmethodclass Animal(ABC):  # 继承自 ABC,表示这是一个抽象类@abstractmethoddef speak(self):  # 抽象方法passclass Dog(Animal):def speak(self):return "Woof!"class Cat(Animal):def speak(self):return "Meow!"# 实例化对象
dog = Dog()
cat = Cat()
print(dog.speak())  # 输出: Woof!
print(cat.speak())  # 输出: Meow!# animal = Animal()  # 这将引发错误,因为不能实例化抽象类

在这个示例中,' Animal ' 是一个抽象类,定义了一个抽象方法 ' speak ' 。子类  ' Dog ' 和 ' Cat ' 必须实现这个方法,否则会引发错误。抽象类的使用使得接口的实现变得一致,并确保所有子类都具备特定的方法。

八、动态添加内容

Python 是一门动态语言,允许我们在运行时向类和实例添加属性和方法。这种灵活性使得 Python 在许多场景下非常强大。

1. 添加实例属性

我们可以在实例创建后直接为实例添加新的属性。

class Cup:def __init__(self, capacity):self.capacity = capacity# 创建实例
my_cup = Cup(300)
my_cup.color = "Blue"  # 动态添加实例属性
print(my_cup.color)  # 输出: Blue

2. 添加实例方法

可以使用 ' types.MethodType ' 动态添加实例方法。注意,动态添加的方法的第一个参数必须是 'self ' 。

import typesdef new_method(self):return f"This cup has a capacity of {self.capacity} ml."my_cup.new_method = types.MethodType(new_method, my_cup)  # 动态添加实例方法
print(my_cup.new_method())  # 输出: This cup has a capacity of 300 ml.

3. 添加类属性和方法

同样地,我们可以向类本身动态添加属性和方法。

Cup.color = "Red"  # 动态添加类属性
print(Cup.color)  # 输出: Reddef class_method(cls):return f"This class has the capacity: {cls.color}"Cup.class_method = classmethod(class_method)  # 动态添加类方法
print(Cup.class_method())  # 输出: This class has the capacity: Red

九、总结

通过本篇文章,我们深入了解了 Python 中的类和面向对象编程的基本概念,包括:

类与实例:类是对象的模板,实例是具体的对象。类定义了属性和行为,实例则包含具体的数据。
'self' 关键字:用于引用实例本身,允许在方法中访问实例属性和方法。
魔法函数:特殊的方法,允许我们定义对象的行为(如初始化、比较和运算),包括 ' __init__ '、 ' __str__ ' 、' __len__ ' 等。
构造函数与析构函数:用于创建和销毁实例,管理资源。构造函数 ' __new__ ' 和析构函数            '  __del__ '  使得我们可以控制实例的创建和销毁过程。
面向对象编程的三大特性:
封装:将数据和方法结合在一起,保护对象的内部状态。
继承:允许子类继承父类的属性和方法,促进代码重用。
多态:允许不同类的对象通过相同的接口进行操作,提高代码的灵活性和可扩展性。
抽象类:用于定义接口,强制子类实现特定的方法,提供一致性。
动态添加内容:Python 允许在运行时向类和实例添加属性和方法,增加了编程的灵活性。

面向对象编程的优势在于它将数据和功能封装在一起,使代码更加模块化可读且易于维护。能帮助我们更好地组织代码,提高开发效率。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/387263.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

计算计中的推理与调用

计算计是一个新的概念,它强调了计算与谋算(算计)的融合和互动过程。这个概念指的是在现代科技和商业环境中,越来越多地将计算能力与战略性思维结合起来,以解决复杂问题、优化决策和实现目标。具体来说,计算…

vue3组件通信(一)

组件通信 一.props(父<>子)二.自定义事件&#xff08;子>父&#xff09;三.mitt(实现任意组件通信)四.v-model(父<>子)(1).v-model的本质(2).组件标签中v-model的本质(3).$event到底是什么 概况 一.props(父<>子) 使用频率最高 若 父传子&#xff1a;属性…

红酒标签设计:艺术与品味的结合

在红酒的世界里&#xff0c;每一瓶酒都如同一位优雅的舞者&#xff0c;在酒柜的舞台上静静诉说着自己的故事。而红酒的标签&#xff0c;则是这位舞者身上较华丽的舞裙&#xff0c;它不仅是红酒的身份证明&#xff0c;更是艺术与品味的很好结合。今天&#xff0c;我们就来聊聊红…

【Vue3】组件生命周期

【Vue3】组件生命周期 背景简介开发环境开发步骤及源码 背景 随着年龄的增长&#xff0c;很多曾经烂熟于心的技术原理已被岁月摩擦得愈发模糊起来&#xff0c;技术出身的人总是很难放下一些执念&#xff0c;遂将这些知识整理成文&#xff0c;以纪念曾经努力学习奋斗的日子。本…

基于vue2 + Ant Design 封装input(输入)下拉Table表格

封装 AInputTable 组件 <!--下拉Table--> <template><div class"input-select-table" ref"inputTableRef" v-clickoutside"handleHide"><div class"input-select-table-input" click"disabled?this:hand…

【信创】samba的命令行使用 _ 统信 _ 麒麟 _ 中科方德

原文链接&#xff1a;【信创】samba的命令行使用 | 统信 | 麒麟 | 中科方德 Hello&#xff0c;大家好啊&#xff01;今天给大家带来一篇关于在信创终端操作系统上使用Samba命令操作的文章。Samba是一种用于实现文件和打印共享的免费软件&#xff0c;它允许不同操作系统&#xf…

Android studio IDE 使用日志 2024/7/30

Android studio IDE 使用日志 时间:2024/7/30 11:10 配置 安装中文语言包,汉化操作界面:下载地址 根据版本信息下载 设置中选择安装插件,选择压缩包自动安装 项目的文件夹目录结构 .gradle :包含了Gradle构建系统,自动编译工具产生的文件 .idea :包含IDEA&#xff08;‌A…

UDP程序设计

UDP协议概述 UDP&#xff0c;User Datagram Protocol&#xff0c;用户数据报协议&#xff0c;是一个简单的面向数据报(package-oriented)的传输层协议&#xff0c;规范为&#xff1a;RFC 768。 UDP提供数据的不可靠传递&#xff0c;它一旦把应用程序发给网络层的数据发送出去…

设计模式16-代理模式

设计模式16-代理模式 动机定义与结构模式定义结构 代码推导特点应用总结实例说明1. 远程代理2. 虚拟代理3. 保护代理4. 智能引用代理 动机 在面向对象系统中有一些对象由于某种原因比如对象创建的开销很大或者某些操作需要安全控制&#xff0c;或者需要进程外的访问等情况。直…

Java面试八股之Spring如何解决循环依赖

Spring如何解决循环依赖 在Spring框架中&#xff0c;循环依赖问题通常发生在两个或多个Bean相互依赖的情况下。Spring为了解决循环依赖问题&#xff0c;采用了不同的策略&#xff0c;这些策略主要取决于Bean的作用域以及依赖注入的方式。下面是一些关键点&#xff1a; 单例Be…

centos安装python 3.9

centos安装python 3.9 1. 准备工作 安装必要的构建工具和依赖项&#xff1a; sudo yum groupinstall "Development Tools" sudo yum install -y zlib-devel bzip2-devel openssl-devel ncurses-devel sqlite-devel readline-devel tk-devel gdbm-devel db4-devel …

轻量级服务器资源监控平台Beszel

什么是 Beszel &#xff1f; Beszel 是一个轻量级平台&#xff0c;借助 Beszel&#xff0c;可以访问 CPU 和内存使用情况的历史数据&#xff0c;以及 Docker 容器指标&#xff08;例如特定于容器的 CPU 和内存统计信息&#xff09;。还能收到针对潜在问题的可自定义警报通知&am…

【Golang 面试 - 进阶题】每日 3 题(八)

✍个人博客&#xff1a;Pandaconda-CSDN博客 &#x1f4e3;专栏地址&#xff1a;http://t.csdnimg.cn/UWz06 &#x1f4da;专栏简介&#xff1a;在这个专栏中&#xff0c;我将会分享 Golang 面试中常见的面试题给大家~ ❤️如果有收获的话&#xff0c;欢迎点赞&#x1f44d;收藏…

基于Django与spark的国漫推荐系统

文章目录 有需要本项目的代码或文档以及全部资源&#xff0c;或者部署调试可以私信博主项目介绍每文一语 有需要本项目的代码或文档以及全部资源&#xff0c;或者部署调试可以私信博主 项目介绍 近年来&#xff0c;随着互联网的蓬勃发展&#xff0c;企事业单位对信息的管理提…

C#知识|文件与目录操作:对象的创建、保存、读取

哈喽&#xff0c;你好啊&#xff0c;我是雷工&#xff01; 面向对象编程的特点就是一切皆对象&#xff0c;操作的也是对象&#xff0c;本节学习文件与目录操作中&#xff0c;对象的保存&#xff1b; 以下为学习笔记。 01 对象的特点 ①&#xff1a;对象运行在内存中&#xff…

二刷代码随想录训练营Day 11| 150. 逆波兰表达式求值、239. 滑动窗口最大值、347.前 K 个高频元素、总结

1.逆波兰表达式 题目链接/文章讲解/视频讲解&#xff1a;代码随想录 代码&#xff1a; class Solution { public:int evalRPN(vector<string>& tokens) {stack<long long> st;for(int i 0; i < tokens.size(); i){if(tokens[i] "" || tokens[i…

vue里给img的src绑定数据失效

起因 在v-for遍历数据时想要通过给img的src单向绑定 图片路径时出现问题 解决过程 上网查说是webpack构建时识别不到&#xff0c;直接不单绑数据&#xff0c;写死试试看 解决方案 直接require导入图像文件模块

热门超声波清洗机有哪些?小型超声波清洗机推荐

在繁忙的工作和生活中&#xff0c;许多人常常会因为种种原因忽略日常的小事&#xff0c;比如忘记清洁手表、眼镜、首饰等常用物品。实际上&#xff0c;这些物品表面不仅积累了灰尘和污垢&#xff0c;特别是跟眼部朝夕相处的眼镜&#xff0c;还可能滋生各种致病细菌&#xff0c;…

【数据分享】《内蒙古省统计年鉴》2000-2023

而今天要限时免费分享的数据就是2000-2023年间出版的《内蒙古省统计年鉴》并以多格式提供免费下载。&#xff08;无需分享朋友圈即可获取&#xff09; 数据介绍 位于中国北部的内蒙古自治区&#xff0c;以其独特的地理和文化特性&#xff0c;成为中国经济发展的重要组成部…

京东科技集团将在香港发行与港元1:1挂钩的加密货币稳定币

据京东科技集团旗下公司京东币链科技(香港)官网信息&#xff0c;京东稳定币是一种基于公链并与港元(HKD) 1:1挂钩的稳定币&#xff0c;将在公共区块链上发行&#xff0c;其储备由高度流动且可信的资产组成&#xff0c;这些资产安全存放于持牌金融机构的独立账户中&#xff0c;通…