Python实例化中默认值的行为及应用
Python实例化中默认值的行为及应用
适合初学者阅读
本文要点
- 使用可变对象作为默认参数会导致所有实例共享同一对象,引发意外的数据修改。
- 不可变对象作为默认参数时,每次实例化都会创建新的对象,不会共享数据。
- 推荐使用
None作为默认值,并在__init__方法中进行适当的初始化以避免共享问题。 - Python中的所有数据都是通过引用来访问的对象,理解这一点有助于正确处理默认参数。
引言
在Python中,理解类构造函数(__init__方法)中的默认参数行为对于编写高效且无误的代码至关重要。本文将通过一个具体的例子来探讨当使用可变对象(如列表)作为默认参数时可能出现的问题,并提供解决这些问题的最佳实践。
问题描述
考虑以下Python代码:
class class_A:def __init__(self, name: str, a_default_list_value=[], a_default_none_value=None, a_default_str_value="~"):self.name = nameself.value_1 = a_default_list_valueself.value_2 = a_default_none_valueself.value_3 = a_default_str_valueif __name__ == "__main__":object_1 = class_A("object_1")object_2 = class_A("object_2")print(id(object_1), ": ", object_1.name, " ", id(object_1.value_1), ": ", repr(object_1.value_1), " ", id(object_1.value_2), ": ", repr(object_1.value_2), " ", id(object_1.value_3), ": ", repr(object_1.value_3))print(id(object_2), ": ", object_2.name, " ", id(object_2.value_1), ": ", repr(object_2.value_1), " ", id(object_2.value_2), ": ", repr(object_2.value_2), " ", id(object_2.value_3), ": ", repr(object_2.value_3))object_2.value_3 = "!"print(id(object_2.value_3), ": ",object_2.value_3)print(id(object_1.value_3), ": ",object_1.value_3)print(id("!"), ": ", "!")# 复杂数据结构object_2.value_2 = []print(id(object_2.value_2), ": ",object_2.value_2)print(id(object_1.value_2), ": ",object_1.value_2)object_1.value_2 = object_2.value_2object_2.value_2.append('...')print(id(object_2.value_2), ": ",object_2.value_2)print(id(object_1.value_2), ": ",object_1.value_2)object_2.value_1.append('._.')print(id(object_2.value_1), ": ",object_2.value_1)print(id(object_1.value_1), ": ",object_1.value_1)object_3 = class_A("object_3")print(id(object_3), ": ", object_3.name, " ", id(object_3.value_1), ": ", repr(object_3.value_1), " ", id(object_3.value_2), ": ", repr(object_3.value_2), " ", id(object_3.value_3), ": ", repr(object_3.value_3))
输出会是这样:
1308360223984 : object_1 1308367676864 : [] 140718652536784 : None 140718653645744 : '~'
1308367549648 : object_2 1308367676864 : [] 140718652536784 : None 140718653645744 : '~'
140718653641280 : !
140718653645744 : ~
140718653641280 : !
1308367714432 : []
140718652536784 : None
1308367714432 : ['...']
1308367714432 : ['...']
1308367676864 : ['._.']
1308367676864 : ['._.']
1308367547248 : object_3 1308367676864 : ['._.'] 140718652536784 : None 140718653645744 : '~'
-
从
value_3可以看到:Python是将字符(串,Python中没有单字符)的值赋值给了
value3(储存于value3地址所指向的内存空间)。之前好像讲过,python的字符赋值方法,算是一种节约空间的办法。没记错的话数字(int)也是这样(这题贴个图)
-
从
value_2和value_3可以看到:最开始的None是指向同一个数据(地址)的,
object_2.value_2指向的空列表被赋值给了object_1.value_2后指向同一数据(地址),说明列表是引用类型(类比C语言)。那么这么看来,好像 python中包括数字、字符串等都是“引用类型”的数据。
-
从
value_1可以看到:对
object_2.value_1的修改也是对a_default_list_value进行修改。所有实例共享同一个默认列表。修改其中一个实例的value_1会影响到其他实例。
这就有问题了:object_3的value_1在生成时就被修改了。在实例上的修改会影响定义中的值,也就是定义的class_A中的a_default_list_value所指向的默认空列表被修改。
为什么会出现这样的情况?
在Python中,所有的数据都是对象,而这些对象是通过引用来访问的。不可变类型(如整数、字符串)在赋值时不会改变原始对象,而是创建新的对象;而对于可变类型(如列表、字典),我们可以通过引用直接修改其内容。因此,当使用可变对象作为默认参数时,如果该对象被修改,则所有使用该默认值的实例都会受到影响。
a_default_list_value所指向的“列表”就相当于是全局变量,唯一。也可以说是class_A中的全局变量(类变量):
class class_A:a_default_list_value_ = []def __init__(self, name: str, a_default_list_value=a_default_list_value_, a_default_none_value=None, a_default_str_value="~"):self.name = nameself.value_1 = a_default_list_valueself.value_2 = a_default_none_valueself.value_3 = a_default_str_value
最佳实践
为了避免上述问题,应该避免使用可变对象作为默认参数。推荐的做法是在__init__方法内部进行适当的初始化。例如:
class ClassA:def __init__(self, name: str, a_default_list_value=None):self.name = nameif a_default_list_value is None:a_default_list_value = []self.value_1 = a_default_list_value
这样可以确保每个实例都有自己的独立副本,从而避免意外的数据共享。
应用场景
- 配置项:在某些情况下,可能希望多个实例共享某些配置信息。这时可以利用类变量或全局变量来实现。
- 缓存:利用共享的可变对象作为缓存,可以在不同实例间共享计算结果,提高性能。
结论
了解Python中对象引用的工作机制对于正确地使用默认参数非常重要。遵循最佳实践可以帮助开发者避免潜在的错误,并编写出更加健壮和高效的代码。
相关文章:
Python实例化中默认值的行为及应用
Python实例化中默认值的行为及应用 适合初学者阅读 本文要点 使用可变对象作为默认参数会导致所有实例共享同一对象,引发意外的数据修改。不可变对象作为默认参数时,每次实例化都会创建新的对象,不会共享数据。推荐使用None作为默认值&…...
【WRF后处理】WRF模拟效果评价及可视化:MB、RMSE、IOA、R
【WRF后处理】模拟效果评价及可视化 准备工作模型评价指标Python实现代码Python处理代码:导入站点及WRF模拟结果可视化图形及评价指标参考在气象和环境建模中(如使用 WRF 模型进行模拟),模型性能评价指标是用于定量评估模拟值与观测值之间偏差和拟合程度的重要工具。 本博客…...
ShenNiusModularity项目源码学习(4:身份认证)
ShenNiusModularity项目有两套启动方式,一种是ShenNius.Admin.Mvc项目启动,该项目为MVC模式,带前台页面,也有后台服务,另一种是ShenNius.Admin.Hosting,该项目启动后仅提供后台服务,供其它前台项…...
python+django自动化部署日志采用WebSocket前端实时展示
一、开发环境搭建和配置 # channels是一个用于在Django中实现WebSocket、HTTP/2和其他异步协议的库。 pip install channels#channels-redis是一个用于在Django Channels中使用Redis作为后台存储的库。它可以用于处理#WebSocket连接的持久化和消息传递。 pip install channels…...
flink学习(6)——自定义source和kafka
概述 SourceFunction:非并行数据源(并行度只能1) --接口 RichSourceFunction:多功能非并行数据源(并行度只能1) --类 ParallelSourceFunction:并行数据源(并行度能够>1) --接口 RichParallelSourceFunction:多功能并行数据源(并行度能够>1) --类 【建议使用的】 ——…...
开发常见问题及解决
1.DBeaver 报Public Key Retrieval is not allowed 在使用DBeaver连接数据库时出现“Public Key Retrieval is not allowed”错误,主要是因为数据库连接配置的安全策略导致的。以下是详细的解释和解决方法: 错误原因 这个错误通常出现在连接MySQL数据…...
python excel接口自动化测试框架!
今天采用Excel继续写一个接口自动化测试框架。 设计流程图 这张图是我的excel接口测试框架的一些设计思路。 首先读取excel文件,得到测试信息,然后通过封装的requests方法,用unittest进行测试。 其中,接口关联的参数通过正则进…...
mybatis:You have an error in your SQL syntax;
完整报错You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near false, false, false, false, false, false, false, false, false, false, false, at line 1 SQL: INSERT INTO user …...
使用 Maven 开发 IntelliJ IDEA 插件
使用 Maven 开发 IntelliJ IDEA 插件的完整流程 1. 创建 Maven 项目 1.1 使用 IntelliJ 创建 Maven 项目 打开 IntelliJ IDEA,点击 File > New > Project。选择 Maven,填写项目名称和 GroupId,例如: GroupId: com.exampl…...
Windows修复SSL/TLS协议信息泄露漏洞(CVE-2016-2183) --亲测
漏洞说明: 打开链接:https://docs.microsoft.com/zh-cn/troubleshoot/windows-server/windows-security/restrict-cryptographic-algorithms-protocols-schannel 可以看到: 找到:应通过配置密码套件顺序来控制 TLS/SSL 密码 我们…...
uniapp生命周期:应用生命周期和页面生命周期
文章目录 1.应用的生命周期2.页面的生命周期 1.应用的生命周期 生命周期的概念:一个对象从创建、运行、销毁的整个过程被称为生命周期 生命周期函数:在生命周期中每个阶段会伴随着每一个函数的出发,这些函数被称为生命周期函数 所有页面都…...
基于SSM的婴幼儿用品商城系统+LW示例参考
1.项目介绍 功能模块:管理员(产品管理、产品分类、会员管理、订单管理、秒杀活动、文章管理、数据统计等)、普通用户(登录注册、个人中心、购物车、我的收藏、各类信息查看等)技术选型:SSM,jsp…...
【工具变量】城市供应链创新试点数据(2007-2023年)
一、测算方式:参考C刊《经济管理》沈坤荣和乔刚老师(2024)的做法,使用“供应链创新与应用试点”的政策虚拟变量(TreatPost)表征。若样本城市为试点城市,则赋值为 1,否则为 0…...
【carla生成车辆时遇到的问题】carla显示的坐标和carlaworld中提取的坐标y值相反
项目需要重新运行了一下generate_car.py的脚本,发现死活生成不了,研究了半天,发现脚本里面生成车辆的坐标值y和carla_ros_bridge_with_example_ego_vehicle.launch脚本打开的驾驶操控界面里面的y值正好是相反数! y1-y2 因为,我运行…...
Jira使用笔记二 ScriptRunner 验证问题创建角色
背景 最近在对公司Jira工作流改造,收到这么一个要求:某些问题类型只有某些角色可以创建。本来是想通过Jira内建的权限控制来处理的。结果点到权限页面,心都凉透了。 好吧,那只能上脚本了。最终使用ScriptRunner的Simple scripte…...
Java线程的使用
Java中的线程是用来实现多任务并发执行的机制。在Java中,主要有两种方式来创建和使用线程:实现Runnable接口和继承Thread类。 实现Runnable接口: 创建一个类,实现Runnable接口,并重写run()方法。在run()方法中定义线程…...
自动化测试工具Ranorex Studio(四十三)-RANOREXPATH编辑器5
代码示例 下面的代码示例将讲解如何使用Ranorex API来编写代码模块,或者是使用用户代码来扩展录制的模块。 在代码中使用对象库 使用对象库等待UI元素 建立Adapter来访问更多的属性和方法 为对象库元素建立一组Adapter 使用Validate类 强制一个测试用例失败 设置aut…...
超高流量多级缓存架构设计!
文章内容已经收录在《面试进阶之路》,从原理出发,直击面试难点,实现更高维度的降维打击! 文章目录 电商-多级缓存架构设计多级缓存架构介绍多级缓存请求流程负载均衡算法的选择轮询负载均衡一致性哈希负载均衡算法选择 应用层 Ngi…...
数据结构(Java)—— ArrayList
1.线性表 线性表( linear list)是n个具有相同特性的数据元素的有限序列。 线性表是一种在实际中广泛使用的数据结构,常见的线性表:顺序表、链表、栈、队列... 线性表在逻辑上是线性结构,也就说是连续的一条直线。但是在…...
实习冲刺第三十三天
102.二叉树的层序遍历 给你二叉树的根节点 root ,返回其节点值的 层序遍历 。 (即逐层地,从左到右访问所有节点)。 示例 1: 输入:root [3,9,20,null,null,15,7] 输出:[[3],[9,20],[15,7]]示例…...
idea大量爆红问题解决
问题描述 在学习和工作中,idea是程序员不可缺少的一个工具,但是突然在有些时候就会出现大量爆红的问题,发现无法跳转,无论是关机重启或者是替换root都无法解决 就是如上所展示的问题,但是程序依然可以启动。 问题解决…...
阿里云ACP云计算备考笔记 (5)——弹性伸缩
目录 第一章 概述 第二章 弹性伸缩简介 1、弹性伸缩 2、垂直伸缩 3、优势 4、应用场景 ① 无规律的业务量波动 ② 有规律的业务量波动 ③ 无明显业务量波动 ④ 混合型业务 ⑤ 消息通知 ⑥ 生命周期挂钩 ⑦ 自定义方式 ⑧ 滚的升级 5、使用限制 第三章 主要定义 …...
相机Camera日志实例分析之二:相机Camx【专业模式开启直方图拍照】单帧流程日志详解
【关注我,后续持续新增专题博文,谢谢!!!】 上一篇我们讲了: 这一篇我们开始讲: 目录 一、场景操作步骤 二、日志基础关键字分级如下 三、场景日志如下: 一、场景操作步骤 操作步…...
Nginx server_name 配置说明
Nginx 是一个高性能的反向代理和负载均衡服务器,其核心配置之一是 server 块中的 server_name 指令。server_name 决定了 Nginx 如何根据客户端请求的 Host 头匹配对应的虚拟主机(Virtual Host)。 1. 简介 Nginx 使用 server_name 指令来确定…...
python如何将word的doc另存为docx
将 DOCX 文件另存为 DOCX 格式(Python 实现) 在 Python 中,你可以使用 python-docx 库来操作 Word 文档。不过需要注意的是,.doc 是旧的 Word 格式,而 .docx 是新的基于 XML 的格式。python-docx 只能处理 .docx 格式…...
第一篇:Agent2Agent (A2A) 协议——协作式人工智能的黎明
AI 领域的快速发展正在催生一个新时代,智能代理(agents)不再是孤立的个体,而是能够像一个数字团队一样协作。然而,当前 AI 生态系统的碎片化阻碍了这一愿景的实现,导致了“AI 巴别塔问题”——不同代理之间…...
【配置 YOLOX 用于按目录分类的图片数据集】
现在的图标点选越来越多,如何一步解决,采用 YOLOX 目标检测模式则可以轻松解决 要在 YOLOX 中使用按目录分类的图片数据集(每个目录代表一个类别,目录下是该类别的所有图片),你需要进行以下配置步骤&#x…...
uniapp微信小程序视频实时流+pc端预览方案
方案类型技术实现是否免费优点缺点适用场景延迟范围开发复杂度WebSocket图片帧定时拍照Base64传输✅ 完全免费无需服务器 纯前端实现高延迟高流量 帧率极低个人demo测试 超低频监控500ms-2s⭐⭐RTMP推流TRTC/即构SDK推流❌ 付费方案 (部分有免费额度&#x…...
Caliper 配置文件解析:config.yaml
Caliper 是一个区块链性能基准测试工具,用于评估不同区块链平台的性能。下面我将详细解释你提供的 fisco-bcos.json 文件结构,并说明它与 config.yaml 文件的关系。 fisco-bcos.json 文件解析 这个文件是针对 FISCO-BCOS 区块链网络的 Caliper 配置文件,主要包含以下几个部…...
如何在最短时间内提升打ctf(web)的水平?
刚刚刷完2遍 bugku 的 web 题,前来答题。 每个人对刷题理解是不同,有的人是看了writeup就等于刷了,有的人是收藏了writeup就等于刷了,有的人是跟着writeup做了一遍就等于刷了,还有的人是独立思考做了一遍就等于刷了。…...
