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]]示例…...
用Python和statsmodels搞定因果推断:手把手教你实现边缘结构模型(MSM)
Python实战:用边缘结构模型(MSM)破解纵向数据因果推断难题 在医疗健康、社会科学和商业分析领域,我们经常面临一个核心挑战:如何从观察性数据中得出可靠的因果结论?当数据具有时间维度时——比如患者的多次就诊记录、用户的连续行…...
EMAC寄存器配置与网络性能优化实战
1. EMAC寄存器概述与核心功能以太网媒体访问控制器(EMAC)是现代嵌入式系统中实现网络通信的核心硬件模块,其寄存器配置直接决定了数据传输的可靠性、实时性和效率。作为硬件与协议栈之间的桥梁,EMAC通过精心设计的寄存器组实现了对…...
EurekaClaw:多智能体AI研究助手,自动化实现从灵感到论文的完整流程
1. 项目概述:从灵感到论文的自动化研究助手在科研工作中,最令人兴奋又最耗费精力的,莫过于从零散的文献、模糊的直觉中,一步步构建出严谨的、可发表的成果。这个过程通常需要经历文献调研、假设生成、理论证明、实验验证和论文撰写…...
【2026实测】直击算法底层逻辑:论文AI率太高?5款工具与3大手改技巧盘点
最近不少学弟学妹在后台跟我倒苦水,说查重率好不容易低了,结果AI率越改越高。眼看临近DDL,生怕又因为这个耽误答辩。 作为已经摸爬滚打出来的老学长,今天我就根据我总结出来的经验,从检测系统的底层逻辑开始讲起&…...
从任务编排到自动化工作流:OpenClaw与Apache Airflow实战解析
1. 项目概述与核心价值最近在GitHub上看到一个挺有意思的项目,叫Charpup/openclaw-task-workflow。光看名字,你可能会有点摸不着头脑——“Charpup”是什么?“OpenClaw”又是什么?这其实是一个典型的、由开发者社区驱动的自动化任…...
多智能体安全协调中的约束推断与CBF应用
1. 多智能体安全协调中的约束推断方法概述在分布式多智能体系统中,安全协调一直是个极具挑战性的问题。想象一下,当一群机器人在仓库中协同搬运货物时,每个机器人可能只知道部分环境信息(比如某些障碍物的位置)&#x…...
仅限前500名获取|Midjourney Blackberry印相专业级Prompt模板包(含EXIF元数据模拟指令)
更多请点击: https://intelliparadigm.com 第一章:Midjourney Blackberry印相的美学溯源与技术本质 Blackberry印相(Blackberry Photographic Process)并非真实存在的传统暗房工艺,而是Midjourney社区中对一类高对比、…...
国产AI模型平台突围战:模力方舟如何用开源生态打破大厂垄断?
当全球AI竞赛进入深水区,中国开发者正面临关键抉择:是继续依赖封闭的大厂生态,还是拥抱更开放的本土化解决方案?2023年中国AI模型平台市场数据显示,百度千帆、阿里ModelScope、华为ModelArts三大平台占据72%市场份额&a…...
解决Modelsim SE 10.6c仿真Vivado 2019乘法器IP核的“.vhd only”难题(附完整脚本)
解决Modelsim SE 10.6c仿真Vivado 2019乘法器IP核的“.vhd only”难题(附完整脚本) 在FPGA设计流程中,Xilinx Vivado与Mentor Modelsim的组合是许多工程师的首选工具链。但当Vivado 2019生成的乘法器IP核仅提供VHDL接口文件(.vhd)时ÿ…...
VSCode界面突然变英文了?别慌,一分钟教你切回中文(附快捷键和常见问题解决)
VSCode界面突然变英文了?别慌,一分钟教你切回中文(附快捷键和常见问题解决) 早上打开VSCode准备写代码,突然发现所有菜单和按钮都变成了英文?这种突如其来的"国际化"体验确实让人措手不及。别担…...
