目录

一.进阶

类方法和静态方法

属性(Properties)

继承和多态

抽象基类(Abstract Base Classes - ABCs)

魔术方法(Magic Methods)

组合和聚合

使用场景

二.私有属性

实现对数据的隐藏

设置私有属性

添加额外对属性操作的方法

三.私有方法

实现对方法的隐藏

直接调用私有方法所出现的问题

四.对象关联

将两个对象关联

调用关联的对象

关联多个对象


一.进阶

在Python中,面向对象编程(OOP)的进阶概念允许开发者构建更复杂、更灵活和易于维护的代码结构,以下是一些关键的进阶特性及其应用。

类方法和静态方法
  • 类方法(class methods): 
  1. 使用@classmethod装饰器定义。
  2. 第一个参数通常是cls,指的是类本身,而非类的实例。
  3. 可以访问和修改类状态。
  • 静态方法(static methods): 
  1. 使用@staticmethod装饰器定义。
  2. 不需要默认的self或cls参数。
  3.  主要用于在类的定义中包含一些与类相关,但在执行时不需要类或实例本身的工具函数。
属性(Properties)

属性允许将方法调用封装成对属性的访问操作,使用@property装饰器可以将类中的方法变为只读属性。

继承和多态
  • 多重继承(multiple inheritance): 
  1. Python支持从多个基类继承,这允许创建复杂的继承结构。
  2. 需要注意的是多重继承可能导致的钻石问题(Diamond Problem)及其解决方案:方法解析顺序(MRO)。
  • 多态(polymorphism): 
  1. Python的多态性是通过鸭子类型(Duck Typing)来实现的:如果它像鸭子一样走路和叫,那么它就是鸭子。
  2. 这意味着函数或方法可以接受任何类型的对象,只要这些对象提供了合适的方法或行为。
抽象基类(Abstract Base Classes - ABCs)
  • 抽象基类是一种定义了一组方法和属性的基类,但至少有一个方法是抽象的。即:该方法没有实现,仅有声明。
  • 使用模块abc和装饰器@abstractmethod来定义抽象方法。
魔术方法(Magic Methods)
  • 通过定义特定的方法,可以改变类的一些默认行为,这些特定方法被称为魔术方法。如:__init__, __str__, __call__等。
  • 例如:通过定义__add__方法,可以让类的实例支持加法操作符。
组合和聚合
  • 组合(composition)和聚合(aggregation)是将对象或类联合在一起的两种方式,通常用于实现has-a关系。
  • 组合意味着一个对象完全拥有另一个对象,而聚合则允许对象有更独立的生命周期。
使用场景

这些进阶特性在许多场合都非常有用,例如:

  • 设计模式的实现:单例模式、工厂模式、策略模式等。
  • 构建框架或库,封装复杂的逻辑。
  • 处理复杂的数据结构,如图、树,和更高级的集合类型。
  • 提供API时隐藏内部实现的细节,仅暴露简洁的接口。

掌握Python中的面向对象编程的进阶概念,可以帮助开发者在编写Python代码时具备更高的灵活性和表达能力,构建出更加健壮、可重用和易于维护的软件。

二.私有属性

案例演示

class Cat:def __init__(self, new_name, new_age):self.name = new_nameself.age = new_agedef print_info(self):print("我叫%s,今年%s了" % (self.name, self.age))# 创建猫对象
cat = Cat("波斯猫", 4)
# 调用方法
cat.print_info()
# 尝试修改属性
cat.age = -10
# 调用方法
cat.print_info()

如果运行上述代码,会发现,第二次输出的信息有误:我叫波斯猫,今年-10岁了

之所以出现这样的错误,究其原因是因为:我们通过对象直接给实例属性赋值的这种方式容易出错

如果在赋值的时候,是通过一个实例方法的调用,在方法中对数据进行严格的检查,合格的数据可以给属性设置,不合格的数据就提醒开发者,这样一来就能够保证数据的准确性了。

那该怎样实现呢?

实现对数据的隐藏

答:

1. 设置属性为私有属性

2. 添加额外对属性操作的方法

设置私有属性

在Python中,如果想要设置为私有的属性,那么仅仅需要在定义属性时在前面加两个下划线__即可

既然有了私有属性,那对象能够直接操作它么?

答:不能,否则就没有私有的作用了

示例如下:

class Teacher:def __init__(self):self.name = "小明"self.__age = 18  # 这个属性就是私有属性t = Teacher()
print(t.name)  # 能够获取
print(t.__age)  # 此时会程序报错,因为__age是私有属性,不能通过对象直接操作
添加额外对属性操作的方法

想要实现对私有属性的操作,我们需要定义方法,在方法中操作

示例如下:

class Teacher:def __init__(self):self.name = "小明"self.__age = 18  # 这个属性就是私有属性def set_age(self, new_age):if 1 <= new_age <= 120:self.__age = new_ageprint("设置年龄成功")else:print("年龄数据有误...")def get_age(self):return self.__aget = Teacher()
t.set_age(20)  # 设置年龄
print(t.get_age())  # 获取年龄

简单总结

1.操作属性有两种方法:

  • 直接通过对象修改:对象名.属性名 = 数据
  • 通过方法间接修改:对象名.方法名(数据)

2.通过使用方法来进行修改,就可以在方法中进行数据合法性的检查

3.通过__可以将属性变为私有属性,这样就防止了通过对象直接操作属性时可能带来的隐患

三.私有方法

引入

生活中我们肯定去过银行办理过业务,我们可以从银行的大门进入大厅,取号等待办理业务,可以在大厅里来回走动,这个区域是所有人都可以随意进出的。而银行办公人员工作的地方,只能有相应的权限的办公人员才能进出,这个区域对于外来办理业务的人员来说是禁止的。

通过上述的描述,大家能够理解了一件事情,即访问的地方不同需要的权限不同

那么试想,一个较大软件系统肯定有很多个可以让用户直接调用的接口(API可以简单理解为方法)这些接口可以任意调用,而有些接口就不能使用。

Python中,我们把可以通过对象直接调用的方法叫做公有方法,不能通过对象直接调用的方法叫做私有方法

实现对方法的隐藏

对于定义私有方法的方式与定义私有属性基本相同,就是在方法的前面添加__(即两个下划线__)

示例如下:

class BankService:def __init__(self, money=5000):self.money = moneydef __bank_to_bank(self):if self.money >= 5000:print("这里是银行之间的转账代码...")return Trueelse:return Falsedef transfer(self):if self.money > 10000:if self.__bank_to_bank():print("转账成功...")else:print("转账失败...")else:print("都没钱,还转什么啊!自己留着花吧!")bank_service = BankService(10001)
bank_service.transfer()  # 可以调用,是公有方法运行测试(转账成功):这里是银行之间的转账代码...
转账成功...运行测试(转账失败):都没钱,还转什么啊!自己留着花吧!

注意点:Python中没有像C++中public和private这些关键字来区别公有和私有,它是以命名方式来区分。如果在名字前面加了两个下划线__,则表明该属性是私有,否则为公有。

直接调用私有方法所出现的问题

代码示例:

上述代码  加入bank_service.__bank_to_bank()  # 不可以调用,是私有方法运行结果:
Traceback (most recent call last):File "/Users/poppies/Documents/python_code/私有方法代码测试.py", line 25, in <module>bank_service.__bank_to_bank()  # 不可以调用,是私有方法
AttributeError: 'BankService' object has no attribute '__bank_to_bank'
四.对象关联

概述

我们在上学的时候,每个同学是一个对象,那么教室也是一个对象。每个同学肯定是属于某一个教室的,例如张三是爬虫一班的。那么怎样才能用代码来实现他们之间的关系呢?

将两个对象关联

如果当前的教室对象与学生对象是没有任何关系关联的。如果想要实现学生属于教室,那么只需要两步就能实现

  1. 搞清楚谁属于谁,例如上述示例中,学生属于教室
  2. 在范围大的那个对象中,定义一个属性存储范围小的对象引用即可

 代码示例:

class ClassRoom:def __init__(self, name):self.cls_name = nameclass Student:def __init__(self, name):self.stu_name = name# 创建一个教室对象
room_1 = ClassRoom("python一班")# 创建一个学生对象
stu_1 = Student("安娜")# 直接给教室对象添加属性
room_1.stu_obj = stu_1
调用关联的对象

上述代码已经完成了对象学生与教室的关联,那么怎样调用呢?格式如下:

# 如果A对象中的某个属性指向了B对象,那么调用方式
A.xxx  # 此时就是指的B对象# 如果想要调用B对象中的某方法,那么就再接着.yyy方法即可
A.xxx.yyy()

代码示例:

class ClassRoom:def __init__(self, name):self.cls_name = nameself.stu_obj = None  # 一般情况下在本类的其它方法中用到的实例属性,都要在__init__方法中定义def add_new_stu(self, stu):"""定义新方法用来完成关联"""self.stu_obj = stuclass Student:def __init__(self, name):self.stu_name = name# 创建一个教室对象
room_1 = ClassRoom("python一班")# 创建一个学生对象
stu_1 = Student("安娜")# 调用方法将学生添加到对象中
room_1.add_new_stu(stu_1)# 调用学生的姓名
# 教室对象.学生.姓名
print(room_1.stu_obj.stu_name)运行结果:
安娜
关联多个对象

既然关联一个对象搞懂了,那么关联多个也就手到擒来,方式如下:

  1. 在范围大的那个对象中再定义一个新的属性,通过设置属性指向新的对象
  2. 如果关联的新的对象与之前关联的对象类型相同,可以考虑用列表、字典、集合等方式将它们关联

实现将多个学生关联到一个教室:

class ClassRoom:def __init__(self, name):self.cls_name = nameself.stu_list = list()def add_new_stu(self, stu):self.stu_list.append(stu)class Student:def __init__(self, name):self.stu_name = name# 创建一个教室对象
room = ClassRoom("python爬虫班")# 创建多个学生对象
stu_1 = Student("安娜")
stu_2 = Student("小明")
stu_3 = Student("小红")# 调用方法将学生添加到对象中
room.add_new_stu(stu_1)
room.add_new_stu(stu_2)
room.add_new_stu(stu_3)# 调用学生的姓名
# 教室对象.列表[下标].姓名
print(room.stu_list[0].stu_name)
print(room.stu_list[1].stu_name)
print(room.stu_list[2].stu_name)

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

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

相关文章

渗透信息收集- Web应用漏洞与指纹信息收集以及情报收集

目录 1. 整体流程与目标概述 2. 常用工具及其用途 2.1 扫描与枚举工具 2.2 情报与数据聚合工具 2.3 流量拦截与手工验证工具 3. 详细技术手法与步骤 3.1 准备阶段 3.2 主动扫描与指纹识别 3.3 数据交叉验证与漏洞确认 3.4 进一步渗透与隐蔽操作 4. 实际工作经验与注…

ASP.NET代码审计 MVC架构 SQL注入漏洞n

接口路由 /Maintenance/GetMaintenanceList MaintenanceController.cs代码 Maintenance 控制器里面的 GetMaintenanceList 方法 接收参数 id 传进 MaintenanceManager.GetMaintenanceList 方法调用 MaintenanceManager.cs代码 这里 id 和 faultId 不一样是不影响的 C# 按顺序匹…

Python入门Day4

Python中数据的常用操作 数据拷贝 根据以下代码可以看出l1和l2实际上都是对于数据的引用&#xff0c;当l1被改变了&#xff0c;l2也会发生同样的改变&#xff0c;l2 l1只是将l2指向了l1所指向的地址。 >>> l1 [1,2,[3,4],[5,6]] >>> l2 l1 >>>…

计算机网络中的常用表项梳理

核心表项对比 表项 全称 工作层级 主要功能 涉及设备 典型生命周期 MAC表 媒体访问控制表 数据链路层&#xff08;二层&#xff09; Mac地址和端口关系 交换机、网桥 动态学习 FDB表 转发数据库 &#xff08;Forwarding DataBase&#xff09; 数据链路层&#xf…

百度轮岗:任命新CFO,崔珊珊退居业务二线

文 | 大力财经2025 年 7 月 1 日&#xff0c;百度组织再次变革&#xff0c;崔珊珊退居二线引发的行业关注。百度创始人李彦宏发布的内部信&#xff0c;宣布的新一轮组织调整里&#xff0c;崔珊珊退居二线这一变动&#xff0c;格外引人瞩目。崔珊珊&#xff0c;这位在百度人力资…

TAMPER-RTC(STM32F103) 引脚说明

我来查看ST官方手册中关于TAMPER-RTC引脚的具体说明。 Ran tool Ran tool Ran tool Read file: doc/STM32F103VGT6/STM32F103VGT6_specification.txt Read file: doc/STM32F103VGT6/STM32F103VGT6_specification.txt Ran tool Read file: doc/STM32F103VGT6/STM32F103VGT6_spec…

BUUCTF在线评测-练习场-WebCTF习题[极客大挑战 2019]HardSQL1-flag获取、解析

解题思路 打开靶场、熟悉的感觉 上次是过滤了很多字符&#xff0c;用了双写绕过进行注入即可&#xff0c;这次进阶了难度 先老规矩判断下闭合 11 123 报错提示 You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version…

MyBatis动态SQL进阶:复杂查询与性能优化实战

引言 在复杂业务场景中&#xff0c;SQL查询往往需要动态拼接条件、复用代码片段&#xff0c;并支持批量操作。MyBatis的动态SQL功能提供了强大的解决方案&#xff0c;本文将深入解析<choose>条件分支、<sql>片段复用、批量操作优化等核心技巧&#xff0c;助你写出高…

@Transactional 注解失效的场景及原因分析

先分析一下 1&#xff0c;内部调用&#xff0c;原对象调用&#xff0c;不是代理对象调用 2&#xff0c;private方法&#xff0c;源码中&#xff0c;只能是public方法 3&#xff0c;异常被捕获了&#xff0c;事物拦截器&#xff0c;无法感知 4&#xff0c;子线程调用&#x…

使用unity创建项目,进行动画制作

1. 创建unity项目 error: error CS0006: Metadata file Library/PackageCache/com.unity.collab-proxy2.8.2/Lib/Editor/PlasticSCM/log4netPlastic.dll could not be found error CS0006: Metadata file Library/PackageCache/com.unity.collab-proxy2.8.2/Lib/Editor/Plasti…

Centos系统及国产麒麟系统设置自己写的go服务的开机启动项完整教程

1、创建服务文件 在 /etc/systemd/system/ 下新建服务配置文件&#xff08;需sudo权限&#xff09;&#xff0c;例如&#xff1a; sudo nano /etc/systemd/system/mygo.service 如下图&#xff0c;创建的mygo.service 2、创建内容如下&#xff1a; DescriptionThe go HTTP a…

Java面试宝典: IO流

1. 下面哪个流类属于面向字符的输入流() 选项: A. BufferedWriter B. FileInputStream C. ObjectInputStream D. InputStreamReader 答案:D 详细分析: 字符流与字节流的本质区别: 字符流(Character Streams)以Unicode字符为单位操作数据,适用于文本处理字节流(Byte…

黑马python(二十五)

目录&#xff1a;1.数据输出-输出为Python对象2.数据输出-输出到文件中3.综合案例1.数据输出-输出为Python对象2.数据输出-输出到文件中移动文件到文件夹&#xff1a;生成了好多文件&#xff0c;因为Rdd是有分区的 &#xff0c;会把数据分散到各个分区去存储&#xff0c;因为电…

【LeetCode 热题 100】41. 缺失的第一个正数——(解法一)暴力解

Problem: 41. 缺失的第一个正数 题目&#xff1a;给你一个未排序的整数数组 nums &#xff0c;请你找出其中没有出现的最小的正整数。 请你实现时间复杂度为 O(n) 并且只使用常数级别额外空间的解决方案。 文章目录整体思路完整代码时空复杂度时间复杂度&#xff1a;O(N log N)…

在运行 Laravel Sail 前,需安装 Docker Desktop 并完成基础配置/具体步骤

一、安装 Docker Desktop&#xff08;必备环境&#xff09; Windows 系统 &#xff08;windows安装包 有两个版本&#xff09; 架构版本查看 1. Win R‌ 输入 ‌cmd‌ 打开命令提示符&#xff1b; 2. ‌输入命令‌&#xff1a; bash echo %PROCESSOR_ARCHITECTURE% 3. ‌结果…

AI 应用于进攻性安全

一、引言 大语言模型&#xff08;LLM&#xff09;和 AI 智能体的出现推动进攻性安全变革&#xff0c;其在侦察、扫描、漏洞分析、利用、报告五个阶段展现出数据分析、代码生成、攻击场景规划等能力&#xff0c;能提升安全团队效率与扩展性&#xff0c;但存在 “幻觉” 等局限性…

微控制器中的EXTI0(External Interrupt 0)中断是什么?

微控制器中的EXTI0(External Interrupt 0)中断是什么? EXTI0(External Interrupt 0) 是微控制器(如STM32等ARM Cortex-M系列芯片)中的一个外部中断线,专门用于处理来自特定GPIO引脚的外部信号触发中断。以下是详细说明: 1. 基本概念 EXTI(External Interrupt/Event …

EasyGBS平台内置AI算法了,算法成为了视频平台的标配

今年五一的时候立了个flag&#xff08;《国标GB28181平台EasyGBS未来研发方向在哪&#xff1f;》&#xff09;&#xff0c;我想不能再局限在只是满足于传统视频平台的功能&#xff0c;传统的EasyGBS也就是接入几种视频协议&#xff0c;什么RTSP、ONVIF、RTMP、GB28181这些&…

C# 常量与变量

在 C# 中&#xff0c;常量和变量是存储数据的基本方式&#xff1a; // 常量&#xff1a;使用 const 关键字声明&#xff0c;必须在声明时初始化&#xff0c;且值不能改变 const double Pi 3.14159; const string Message "Hello, World!"; ​ // 变量&#xff1a;…

TensorRT-LLM:大模型推理加速的核心技术与实践优势

大型语言模型推理就像让一头300公斤的大熊猫玩平衡木——显存消耗和计算效率这对双胞胎问题随时可能让表演翻车。以主流的7B参数模型为例&#xff0c;FP16精度下仅模型权重就吃掉14GB显存&#xff0c;这还没算上推理过程中不断膨胀的KV Cache——当处理2048长度的对话时&#x…