Python中的类和对象(7)

news2025/1/12 13:23:17

1.私有变量

在大多数面向对象的编程语言中,都存在着私有变量(private variable)的概念,所谓私有变量,就是指通过某种手段,使得对象中的属性或方法无法被外部所访问。

Python 对于私有变量的实现是引入了一种叫 name mangling 的机制(翻译过来叫 “名字改编”、“名称改写” 或者 “名称修饰”),语法是在变量名前面加上两个连续下划线(__):

>>> class C:
...     def __init__(self, x):
...         self.__x = x
...     def set_x(self, x):
...         self.__x = x
...     def get_x(self):
...         print(self.__x)
...
>>> c = C(250)

此时,我们是无法直接通过变量名访问到该变量的:

>>> c.__x
Traceback (most recent call last):
  File "<pyshell#13>", line 1, in <module>
    c.__x
AttributeError: 'C' object has no attribute '__x'

想要访问变量的值,就需要使用指定的接口,比如这段代码中的 set_x() 和 get_x() 方法:

>>> c.get_x()
250
>>> c.set_x(520)
>>> c.get_x()
520

2. name mangling 机制的实现原理

我们看看 dict 属性里面有啥:

>>> c.__dict__
{'_C__x': 250}

虽然这里面没有看到 __x,但是,却多了一个 _C__x 的属性对不对?

访问一下试试:

>>> c._C__x
520

果然如此……这个就是传说中的名字改编术!

做法其实也很简单,就是下横线(_)加上类名,再加上变量的名字。

方法名也是同样的道理:

>>> class D:
...     def __func(self):
...         print("Hello FishC.")
...
>>> d = D()
>>> d.__func()
Traceback (most recent call last):
  File "<pyshell#12>", line 1, in <module>
    d.__func()
AttributeError: 'D' object has no attribute '__func'
>>> d._D__func()
Hello FishC.

注意:name mangling 机制是发生在类实例化对象时候的事情,给对象动态添加属性则不会有同样的效果。

3. 不同数量的前缀下划线含义

不同数量的前缀下划线均有不同的特殊含义:
在这里插入图片描述

4. 效率的提升之道

Python 对象存储属性的工作原理 —— 字典(dict):

>>> class C:
...     def __init__(self, x):
...         self.x = x
...                
>>> c = C(250)
>>> c.x
250
>>> c.__dict__
{'x': 250}

对象动态添加属性,就是将键值对添加到 dict 中:

>>> c.y = 520
>>> c.__dict__
{'x': 250, 'y': 520}

甚至你可以直接通过给字典添加键值对的形式来创建对象的属性:

>>> c.__dict__['z'] = 666
>>> c.__dict__
{'x': 250, 'y': 520, 'z': 666}
>>> c.z
666

但是,字典高效率的背后是以付出更多存储空间为代价的

如果我们明确知道一个类的对象设计出来,就只是需要那么固定的某几个属性,并且不需要有动态添加属性这样的功能,那么利用字典来存放属性,这种空间上的牺牲就是纯纯地浪费!

针对这个情况,Python 专门设计了一个 _ slots _ 类属性,避免了利用字典存放属性造成空间上的浪费。
举个例子:

>>> class C:
...     __slots__ = ['x', 'y']
...     def __init__(self, x):
...         self.x = x
...        
>>> c = C(250)

这样,我们就创建了一个属性受限制的对象。

访问 slots 中列举的属性是没问题的:

>>> c.x
250
>>> c.y = 520
>>> c.y
520

如果想要动态地添加一个属性,那就不好意思了:

>>> c.z = 100
Traceback (most recent call last):
  File "<pyshell#27>", line 1, in <module>
    c.z = 100
AttributeError: 'C' object has no attribute 'z'

这种限制不仅体现在动态添加属性上,如果在类的内部,想创建一个 _slots _ 不包含的属性,也是不被允许的:

>>> class D:
...     __slots__ = ['x', 'y']
...     def __init__(self, x, y, z):
...         self.x = x
...         self.y = y
...         self.z = z
>>> d = D(3, 4, 5)
Traceback (most recent call last):
  File "<pyshell#8>", line 1, in <module>
    d = D(3, 4, 5)
  File "<pyshell#6>", line 6, in __init__
    self.z = z
AttributeError: 'D' object has no attribute 'z'

甚至是 dict 属性,也不存在了:

>>> d.__dict__
Traceback (most recent call last):
  File "<pyshell#23>", line 1, in <module>
    d.__dict__
AttributeError: 'D' object has no attribute '__dict__'

因为使用了 slots 属性,那么对象就会划分一个固定大小的空间来存放指定的属性,这时候 dict 属性就不需要了,空间也就节约了出来。
大家不要小看这点改变……

这里有位国外的老哥,仅仅由于将一个类的三个属性,都改为使用 slots 进行存储,立竿见影地直接节省了 9G 的内存空间
在这里插入图片描述
一行代码,竟然降低了 30% 的内存消耗,确实惊人!

不过这里有一点是需要特别强调的,就是使用 slots 属性的副作用其实也相当明显,那就是要以牺牲 Python 动态语言的灵活性,作为前提。

使用了 slots 属性,就没办法再拥有动态添加属性的功能了……

这可以说是它的一个副作用,但实际上很多开发者却利用这个副作用,来限制类属性的滥用。

最后,还有一点需要大家知道的是,继承自父类的 __ slots _ _ 属性是不会在子类中生效的,Python 只关注各个具体的类中定义的 _ _ slots __ 属性:

>>> class E(C):
...     pass
...
>>> e = E(250)
>>> e.x
250
>>> e.y = 520
>>> e.z = 666
>>> e.__slots__
['x', 'y']

对象e虽然拥有 slots 属性,但它同时也拥有 dict 属性:

>>> e.__dict__
{'z': 666}

5.思维导图

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

MySQL数据库调优————数据库调优维度及测试数据准备

MySQL性能优化金字塔法则 不合理的需求&#xff0c;会造成很多问题。&#xff08;比如未分页&#xff0c;数据需要多表联查等&#xff09;做架构设计的时候&#xff0c;应充分考虑业务的实际情况&#xff0c;考虑好数据库的各种选择&#xff08;比如是否要读写分离&#xff0c;…

Spring IOC Bean标签属性介绍(内含教学视频+源代码)

Spring IOC Bean标签属性介绍&#xff08;内含教学视频源代码&#xff09; 教学视频源代码下载链接地址&#xff1a;https://download.csdn.net/download/weixin_46411355/87442649 目录Spring IOC Bean标签属性介绍&#xff08;内含教学视频源代码&#xff09;教学视频源代码…

jetson nano(ubuntu)安装Cmake

文章目录安装环境一.命令行安装二.Cmake源码编译安装安装环境 jetson nano 系统&#xff1a;4.6.1 一.命令行安装 sudo apt install cmake这种直接安装cmake的方式&#xff0c;其实安装的版本都太老了&#xff0c;这种方式不推荐 二.Cmake源码编译安装 更新一下系统软件 su…

子词嵌入,词的相似性和类比任务

fastText模型提出了一种子词嵌入方法&#xff1a;基于word2vec中的跳元模型&#xff0c;它将中心词表示为其子词向量之和。 字节对编码执行训练数据集的统计分析&#xff0c;以发现词内的公共符号。作为一种贪心方法&#xff0c;字节对编码迭代地合并最频繁的连续符号对。 子…

文献阅读:Finetuned Language Models Are Zero-Shot Learners

文献阅读&#xff1a;Finetuned Language Models Are Zero-Shot Learners 1. 文章简介2. 方法介绍3. 实验 1. 数据集整理2. 基础实验3. 消解实验 1. finetune任务数量2. 模型size3. Instruct Tuning4. Few-Shot5. Prompt Tuning 4. 结论 文献链接&#xff1a;https://arxiv.o…

简单理解小目标分割中的weighted BCE Loss与weighted IoU Loss

这两个损失函数出自《FNet: Fusion, Feedback and Focus for Salient Object Detection》一文中&#xff0c;用于处理显著性检测(二分割)中小目标的问题。对于传统的BCE Loss&#xff0c;其存在以下三个问题&#xff1a; 只是简单的将每个像素求BCE再平均&#xff0c;忽视了目…

day5——冒泡排序,选择排序和插入排序的学习

选择排序冒泡排序插入排序 选择排序 选择排序的基本思路就是&#xff1a; 首先假定第一个的下表为所有元素中最小的一个&#xff0c; 然后用后面的每一个元素跟这个元素进行比较&#xff0c; 如果后面的元素比这个元素更小一点&#xff0c; 那么就将找到的最小的元素的下标和…

【c++】vector实现(源码剖析+手画图解)

vector是我接触的第一个容器&#xff0c;好好对待&#xff0c;好好珍惜&#xff01; 目录 文章目录 前言 二、vector如何实现 二、vector的迭代器&#xff08;原生指针&#xff09; 三、vector的数据结构 图解&#xff1a; 四、vector的构造及内存管理 1.push_back() …

《爆肝整理》保姆级系列教程python接口自动化(十二)--https请求(SSL)(详解)

简介 本来最新的requests库V2.13.0是支持https请求的&#xff0c;但是一般写脚本时候&#xff0c;我们会用抓包工具fiddler&#xff0c;这时候会 报&#xff1a;requests.exceptions.SSLError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:590) 小编…

C++:提高篇: 栈-寄存器和函数状态:windows X86-64寄存器介绍

寄存器1、什么是寄存器2、寄存器分类3、windows X86寄存器命名规则4、寄存器相关术语5、寄存器分类5.1、RAX(accumulator register)5.2、RBX(Base register)5.3、RDX(Data register)5.4、RCX(counter register)5.5、RSI(Source index)5.6、RDI(Destination index)5.7、RSP(stac…

iptables和nftables的使用

文章目录前言iptable简介iptable命令使用iptables的四表五链nftables简介nftables命令的时候nftables与iptables的区别iptables-legacy和iptables-nft实例将指定protocol:ip:port的流量转发到本地指定端口前言 本文展示了&#xff0c;iptables和nftable命令的使用。 # 实验环…

win10 安装rabbitMQ详细步骤

win10 安装rabbitMQ详细步骤 win10 安装rabbitMQ详细步骤win10 安装rabbitMQ详细步骤一、下载安装程序二、安装配置erlang三、安装rabbitMQ四、验证初始可以通过用户名&#xff1a;guest 密码guest来登录。报错&#xff1a;安装RabbitMQ出现Plugin configuration unchanged.问题…

力扣SQL刷题10

目录标题618. 学生地理信息报告--完全不会的新题型1097. 游戏玩法分析 V - 重难点1127. 用户购买平台--难且不会618. 学生地理信息报告–完全不会的新题型 max()函数的功效&#xff1a;&#xff08;‘jack’, null, null&#xff09;中得出‘jack’&#xff0c;&#xff08;nul…

基于微信小程序图书馆座位预约管理系统

开发工具&#xff1a;IDEA、微信小程序服务器&#xff1a;Tomcat9.0&#xff0c; jdk1.8项目构建&#xff1a;maven数据库&#xff1a;mysql5.7前端技术&#xff1a;vue、uniapp服务端技术&#xff1a;springbootmybatis本系统分微信小程序和管理后台两部分&#xff0c;项目采用…

索引的基本介绍

索引概述-优缺点 索引介绍&#xff1a;索引是一种高效获取数据的数据结构&#xff1b; 索引优点&#xff1a;提供查询效率&#xff1b;降低IO成本&#xff1b;怎么减低IO成本呢&#xff1f;因为数据库的数据是存放在磁盘的&#xff0c;你要操作数据就会涉及到磁盘IO&#xff0…

Windows11 安装Apache24全过程

Windows11 安装Apache24全过程 一、准备工作 1、apache-httpd-2.4.55-win64-VS17.zip - 蓝奏云 2、Visual Studio Code-x64-1.45.1.exe - 蓝奏云 二、实际操作 1、将下载好的zip文件解压放到指定好的文件夹。我的是D:\App\PHP下 个人习惯把版本号带上。方便检测错误。 2…

数组常使用的方法

1. join (原数组不受影响)该方法可以将数组里的元素,通过指定的分隔符,以字符串的形式连接起来。返回值:返回一个新的字符串const arr[1,3,4,2,5]console.log(arr.join(-)&#xff1b;//1-3-4-2-52. push该方法可以在数组的最后面,添加一个或者多个元素结构: arr.push(值)返回值…

(考研湖科大教书匠计算机网络)第四章网络层-第一、二节:网络层概述及其提供的服务

获取pdf&#xff1a;密码7281专栏目录首页&#xff1a;【专栏必读】考研湖科大教书匠计算机网络笔记导航 文章目录一&#xff1a;网络层概述&#xff08;1&#xff09;概述&#xff08;2&#xff09;学习内容二&#xff1a;网络层提供的两种服务&#xff08;1&#xff09;面向连…

nginx越界读取缓存漏洞(CVE-2017-7529)

range格式: Range: <unit><range-start>- Range: <unit><range-start>-<range-end> Range: <unit><range-start>-<range-end>, <range-start>-<range-end> range事例&#xff1a; Range: bytes500-999 //表示第…

Spring Security简介

前面我们已经完成了传智健康后台管理系统的部分功能&#xff0c;例如检查项管理、检查组管理、套餐管理、预 约设置等。接下来我们需要思考2个问题&#xff1a; 问题1&#xff1a;在生产环境下我们如果不登录后台系统就可以完成这些功能操作吗&#xff1f; 答案显然是否定的&am…