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]]示例…...
Uniapp开发下拉刷新功能onPullDownRefresh/onReachBottom
文章目录 1.onPullDownRefresh2.onReachBottom 1.onPullDownRefresh 在 js 中定义 onPullDownRefresh 处理函数(和onLoad等生命周期函数同级),监听该页面用户下拉刷新事件。 需要在 pages.json 里,找到的当前页面的pages节点&am…...
什么是 C++ 中的函数对象?函数对象与普通函数有什么区别?如何定义和使用函数对象?
1) 什么是 C 中的函数对象?它有什么特点? 在 C 中,函数对象(也称为仿函数或 functor)是一种重载了 operator() 的对象。这意味着这些对象可以像函数一样被调用。函数对象通常用于需要传递行为(即代码&…...
PointNet++论文复现
✨✨ 欢迎大家来访Srlua的博文(づ ̄3 ̄)づ╭❤~✨✨ 🌟🌟 欢迎各位亲爱的读者,感谢你们抽出宝贵的时间来阅读我的文章。 我是Srlua小谢,在这里我会分享我的知识和经验。&am…...
【VUE】el-table表格内输入框或者其他控件规则校验实现
1、封装组件 1、规则校验一般基于form表单实现,因此需要给具体控件套一层form表单 新建组件input-required.vue,内容如下 <template><div><el-form ref"formRef" :model"form" :rules"formRules" label-…...
django开发中html继承模板样式
存在问题: django开发中,不同页面样式相同,如何共用一套母版,避免每个页面都重复写样式; 解决方案: 添加一个母版,如“layout.html”,在需要继承的位置添加{% block content %}{% e…...
MT6769/MTK6769核心板规格参数_联发科安卓主板开发板方案
MT6769安卓核心板具有集成的蓝牙、FM、WLAN和GPS模块,是一个高度集成的基带平台,结合了调制解调器和应用处理子系统,以支持LTE/LTE-A和C2K智能手机应用。 该芯片集成了两个工作频率高达2.0GHz的ARMCortex-A75内核、六个工作频率高达1.70GHz的…...
鸿蒙进阶篇-状态管理之@Provide与@Consume
大家好,这里是鸿蒙开天组,今天我们来学习一下状态管理中的Provide与Consume。 一、概述 嘿!大家还记得这张图吗?不记得也要记得哦,因为这张图里的东西,既是高频必考面试题,也是实际开发中&…...
java集合及源码
目录 一.集合框架概述 1.1集合和数组 数组 集合 1.2Java集合框架体系 常用 二. Collection中的常用方法 添加 判断 删除 其它 集合与数组的相互转换 三Iterator(迭代器)接口 3.0源码 3.1作用及格式 3.2原理 3.3注意 3.4获取迭代器(Iterator)对象 3.5. 实现…...
GraphRAG访问模式和知识图谱建模
GraphRAG访问模式和知识图谱建模 GraphRAG访问模式和知识图谱建模什么是GraphRAG了解文本分块检索模式图谱建模相关概念图结构 GraphRAG访问模式和知识图谱建模 graphrag.com是一个开源项目,收集了围绕GraphRAG的相关资源,目前正在快速收集大家的投稿。深…...
TCP/IP协议攻击与防范
一、TCP/IP协议攻击介绍 1.1 Internet的结构 LAN:局域网 WAN:广域网 WLAN:无线局域网 私有IP地址与公有IP地址? 私有地址:A类:10.0.0.0~10.255.255.255 B类:172.16.0.0~172.31.255.255…...
做跨境的网站/营销软件
前一段写了一篇“使用Windows Mobile 6.5访问Exchange2010邮箱”,看到大家很感兴趣,并有朋友询问如何使用手机版的OC,今天整好有时间,把这段内容给补充上,希望能给朋友们帮上忙。当然如果想用手机和公司的OC通信,我们需…...
热门的网站模板/百度搜索智能精选入口
流式编程Stream 什么是Stream? Stream它并不是一个容器,它只是对容器的功能进行了增强,添加了很多便利的操作,例如查找、过滤、分组、排序等一系列的操作并且有串行、并行两种执行模式,并行模式充分的利用了多核处理器的优势&am…...
沈阳网站关键词优化多少钱/网页制作模板
摘要:伴随信息技术的快速发展,进一步促进水厂的信息系统化建设成为水厂管理工作的重中之重。依据水厂管理工作的实际业务需求,设计与实现基于B/S的水厂管理信息系统具有现实需求,同时也具有较高的实际性价值和必要性。本系统的设计与实现过程可划分为:需求分析、系统…...
苏州做视频网站广告公司/网站平台怎么推广
Ecshop这款程序虽然目前已经开发的相当成熟了,可是后台的一些功能还是比较烂,原因只有一个那就是它属于开源程序,很多站长们使用这款程序搭建商城,可是由于自己的疏忽不小心忘记了账号密码,这时候再想登陆到后台去就需…...
删掉cache wordpress/万网域名查询官网
原文 对于我们CSS开发者来说经常听到一些关于LESS和SASS的信息,但是我们并不知道这都是什么意思,这篇文章就是为我们而准备的.在调查这些语言后,我已经发现它们都是一些js文件,运行后会产生相应CSS文件给我们.为什么我们要使用LESS和SASS它们呢,因为我们可以避免CSS中需要的重复…...
网站开发的工作流程/百度网盘客户端下载
第一步:获取配置信息。Configuration configuration new Configuration().configure();configure英文是配置的意思, 通过读取的配置图纸,建立一个生产session的工厂。如果你的配置文件是在根目录src下面,则没有参数。如果在其他目…...