Python的类成员变量默认初始值的坑及解决
作者:zzx90 发布时间:2023-12-02 18:46:47
类成员变量默认初始值的坑
问题发现
一个循环内,缺省值初始化同名变量,其中的list成员不是空,会延续之前同名变量的值。
示例代码
# Define class
class Variant():
?? ?# use
?? ?def __init__(self, price = 500, description = 'default description', values = ['', '', '']):
?? ??? ?self.price = price
?? ??? ?self.description = description
?? ??? ?self.values = values
?? ?
?? ?def __str__(self):
?? ??? ?return 'price: {}, description: {}, values: {}'.format(self.price, self.description, self.values)
variant_list = []
# Create instance with same name iteratively
for i in range(3):
?? ?current_variant = Variant()
?? ?if i == 1:
?? ??? ?current_variant.values[2] = 'hello'
?? ?current_variant.price = i
?? ?current_variant.description = 'description of variant: {}'.format(i)
?? ?variant_list.append(current_variant)
?? ?
# Test results
for variant in variant_list:
?? ?print(str(variant))
结果
所有实例的values列表值相同
原因
可选参数默认值的设置在Python中只会被执行一次,也就是定义该函数的时候”如此使用缺省值初始化,list成员指向的是同一个list(地址),如果只是修改其中一个元素(而不是赋值新的list开辟新内存),那么所有instance的list成员都会被修改。
解决方法
直接在构造方法中置为空(self.values = ['', '', '']),之后各个修改值
Python默认值参数
简单粗暴上代码
def fun(a, b=[]):
? ? b += [a]
? ? print(b)
fun(1)
fun(2,[])
fun(3)
是不是看上去很简单,其实暗藏玄机,请大家看一下输出结果,是不是有点让你疑惑^^~
[1]
[2]
[1, 3]
此时你是否也和我有一样的疑惑,为什么 fun(3) 的输出结果是 [1, 3]?
哈哈,不卖关子了,这里是因为,因为函数被定义好后,只会生成一次,所以在函数生成的时候定义的变量 b 的默认值也只会被初始化一次。
因此,当执行fun(1)函数时,没有给 b 传参,所以使用的是 b 的默认值,此时 b 的默认值为[1]。
执行fun(2,[])时,给 b 传了一个[]值(恰好和默认值相同,其实是不同的数据),因此便使用的是传入数据,执行结果便是[2]。
然后在执行fun(3),此刻又没有给 b 传参,所以依旧使用的是 b 的默认值, 而 b 的默认值只会随着函数的生成被生成一次 ( fun(1) 生成过了 ),所以现在的默认值是fun(1)的执行结果[1],因此当fun(3)再次调用时,输出结果便会是[1, 3]。
如果不行出现当前这种情况,而是在函数每次被调用的时候都初始化一次变量
可以用下面这种写法
def function(a, b=None):
? ? b = b if b else [] ?# 明确每次重新定义b
? ? b += [a]
? ? print(b)
function(1)
function(2, [])
function(3)
输出结果:
[1]
[2]
[3]
来源:https://blog.51cto.com/u_8878683/2348528


猜你喜欢
- 本文从算法入手同时通过实例来讲解如何在SQL Server数据库中实现最优最简的整个过程。算法是计算机科学中一个重要的研究方向,是解决复杂问
- zipfile是python里用来做zip格式编码的压缩和解压缩的,由于是很常见的zip格式,所以这个模块使用频率也是比较高的zipfile
- 基础知识在学习该漏洞之前我们需要学习一下前置知识来更好的理解该漏洞的产生原因以及如何利用。 我们先来学习一下框架的基本信息以及反序列化漏洞的
- 介绍当创建一个应用程序时,通常希望能够告诉你的应用程序如何做某事。有两种流行的方法来完成这项任务,你可以让应用程序接受命令行参数,或者创建一
- 数据API数据集方法不会修改数据集,而是创建新数据集。可通过调用 map() 方法将转换应用于每个元素:dataset = dataset.
- Windows10本机环境:win10未安装node,安装了nvm工具,尝试使用nvm安装我开发环境的node版本(10.9.0 or la
- 你是否对获得MySQL改变字符集的实际操作感到十分头疼?不用急,以下的文章将会给你正确的解答方案,以下的文章主要是介绍获得MySQL改变字符
- 本文实例讲述了Python smallseg分词用法。分享给大家供大家参考。具体分析如下:#encoding=utf-8 #import p
- 本文实例讲述了pymssql数据库操作MSSQL2005的方法。分享给大家供大家参考。具体如下:使用的MSSQL2005,通过pymssql
- 创建列表sample_list = ['a',1,('a','b')]Python 列表操作
- Python2.6 开始,新增了一种格式化字符串的函数 str.format(),它增强了字符串格式化的功能。基本语法是通过 {} 和 :
- 项目:基于Pymysql的专家随机抽取系统引入库函数:>>> import treelib>>> fro
- 引言实现一个视频压缩的功能,性能优良 压缩视频 从61M 到 11M或者80M到15M视频看起来没有太大损伤缺点:耗时20s (win10,
- 在c语言中可以用system函数调用系统命令并得到输出,通过输出重定向也可以将程序执行的输出保存到文件以供使用,但用起来不是很方便。我这里介
- 1. Python中的异常栈跟踪之前在做Java的时候,异常对象默认就包含stacktrace相关的信息,通过异常对象的相关方法printS
- 转发时请保留此声明信息,这段声明不并会影响你的速度! @author:  
- django启动我们在启动一个django项目的时候,无论你是在命令行执行还是在pycharm直接点击运行,其实都是执行'runse
- 在我们的日常生活工作中,经常会遇到需要上传日志的场景,比如多台机器运行同一个程序,并且需要记录每台机器程序产生的日志,根据相关关键词告警,或
- 以下是引用片段: ImportsSystem.Data ImportsSystem.Data.SqlClient PublicClassFo
- 程序设计中三种基本机构是顺序结构、选择结构和循环结构。顺序结构语句是程序中最基础的语句,赋值语句、输入/输出语句、模块导入语句等都是顺序结构