当前位置: 首页 > news >正文

Python实例化中默认值的行为及应用

Python实例化中默认值的行为及应用

适合初学者阅读

本文要点

  1. 使用可变对象作为默认参数会导致所有实例共享同一对象,引发意外的数据修改。
  2. 不可变对象作为默认参数时,每次实例化都会创建新的对象,不会共享数据。
  3. 推荐使用None作为默认值,并在__init__方法中进行适当的初始化以避免共享问题。
  4. 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_2value_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_3value_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&#xf…...

【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]]示例…...

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器的上位机配置操作说明

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器专为工业环境精心打造,完美适配AGV和无人叉车。同时,集成以太网与语音合成技术,为各类高级系统(如MES、调度系统、库位管理、立库等)提供高效便捷的语音交互体验。 L…...

反向工程与模型迁移:打造未来商品详情API的可持续创新体系

在电商行业蓬勃发展的当下,商品详情API作为连接电商平台与开发者、商家及用户的关键纽带,其重要性日益凸显。传统商品详情API主要聚焦于商品基本信息(如名称、价格、库存等)的获取与展示,已难以满足市场对个性化、智能…...

【JVM】- 内存结构

引言 JVM:Java Virtual Machine 定义:Java虚拟机,Java二进制字节码的运行环境好处: 一次编写,到处运行自动内存管理,垃圾回收的功能数组下标越界检查(会抛异常,不会覆盖到其他代码…...

Go 语言接口详解

Go 语言接口详解 核心概念 接口定义 在 Go 语言中,接口是一种抽象类型,它定义了一组方法的集合: // 定义接口 type Shape interface {Area() float64Perimeter() float64 } 接口实现 Go 接口的实现是隐式的: // 矩形结构体…...

全球首个30米分辨率湿地数据集(2000—2022)

数据简介 今天我们分享的数据是全球30米分辨率湿地数据集,包含8种湿地亚类,该数据以0.5X0.5的瓦片存储,我们整理了所有属于中国的瓦片名称与其对应省份,方便大家研究使用。 该数据集作为全球首个30米分辨率、覆盖2000–2022年时间…...

c++ 面试题(1)-----深度优先搜索(DFS)实现

操作系统:ubuntu22.04 IDE:Visual Studio Code 编程语言:C11 题目描述 地上有一个 m 行 n 列的方格,从坐标 [0,0] 起始。一个机器人可以从某一格移动到上下左右四个格子,但不能进入行坐标和列坐标的数位之和大于 k 的格子。 例…...

Spring Boot+Neo4j知识图谱实战:3步搭建智能关系网络!

一、引言 在数据驱动的背景下,知识图谱凭借其高效的信息组织能力,正逐步成为各行业应用的关键技术。本文聚焦 Spring Boot与Neo4j图数据库的技术结合,探讨知识图谱开发的实现细节,帮助读者掌握该技术栈在实际项目中的落地方法。 …...

MySQL 8.0 OCP 英文题库解析(十三)

Oracle 为庆祝 MySQL 30 周年,截止到 2025.07.31 之前。所有人均可以免费考取原价245美元的MySQL OCP 认证。 从今天开始,将英文题库免费公布出来,并进行解析,帮助大家在一个月之内轻松通过OCP认证。 本期公布试题111~120 试题1…...

高效线程安全的单例模式:Python 中的懒加载与自定义初始化参数

高效线程安全的单例模式:Python 中的懒加载与自定义初始化参数 在软件开发中,单例模式(Singleton Pattern)是一种常见的设计模式,确保一个类仅有一个实例,并提供一个全局访问点。在多线程环境下,实现单例模式时需要注意线程安全问题,以防止多个线程同时创建实例,导致…...

C++.OpenGL (14/64)多光源(Multiple Lights)

多光源(Multiple Lights) 多光源渲染技术概览 #mermaid-svg-3L5e5gGn76TNh7Lq {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-3L5e5gGn76TNh7Lq .error-icon{fill:#552222;}#mermaid-svg-3L5e5gGn76TNh7Lq .erro…...