python函数传参传递dict/list/set等类型的问题

python3 : 可变数据类型/不可变数据类型 与函数传参 Python3 函数中,全局变量为 不可变数据 或 可变数据 ,并且,用作函数参数, 函数的局部变量可能会导致全局变量的数值变化。 阅读详情

传参时传递可变对象,实际上传的是指向内存地址的指针/引用

这个标题是我的结论,也是我在做项目过程查到的。学过C的都知道,函数传参可以传值,也可以传指针。指针的好处此处不再赘述。

先上代码看看效果:

def trans(var):
    return var

source = {1: 1}
dist = trans(source)
source[2] = 2
print(source)
print(dist)

运行结果:

{1: 1, 2:2}
{1: 1, 2:2}

可以看到改变了source时,dist也跟着改变了。原因就是source是可变对象,传递参数时,传的是其引用(C的指针)。dist和source都指向了同一片内存空间。在运行source[2] = 2时,是对内存空间的数据的变更,所以dist也跟着变化。

有什么作用呢?场景应该很多,不过本人资历尚浅,想不到典型场景,就拿自己的项目举例。

项目中我定义了一个类,这个类用来读写配置,预存一些json配置,客户端可以读取配置,当预存的配置不包含客户端读取的配置时,就从设备读取。

我需要这个类实例化出多个对象,对应多个客户端。但我希望预存的配置可以是公共的,这样对于陌生配置,不用所有的客户端请求时,都需要从设备读取。

一开始我是这么写的:

global dataset
dataset = {}

class Config(object):
    def __init__(self, device_url):
        self.device_url = device_url
    
    def get_config(self, key):
        global dataset
        
        if key in dataset:
            return dataset.get(key)
        else:
            # 通过device_url从设备获取配置,假如赋值给了value
            dataset[key] = value
            return value
        
    def other_func(self):
        # 其他函数,跟device_url有关
        pass

而后来我需要多份公共配置,甚至要达到1000份以上,显然全局变量并不能很好满足。因为要共用内存,所以我传递可变对象,把代码改成了这样:

class Config(object):
    
    def __init__(self, dataset, device_url):    			# 传递可变对象dataset
        self.dataset = dataset
        self.device_url = device_url
    
    def get_config(self, key):        
        if key in self.dataset:
            return self.dataset.get(key)
        else:
            # 通过device_url从设备获取配置,假如赋值给了value
            self.dataset[key] = value			 			# 可变对象dataset赋值,其他实例化的dataset属性值也会变化
            return value
        
    def other_func(self):
        # 其他函数,跟device_url有关
        pass

列表、字典、集合不一定是可变对象

网上有一堆资料说列表、字典、集合是可变对象,这句话不完全正确。{} [] set((, ))常量不是可变对象。

上述的Config类,如果实例化时传递{},就不能共享配置。

config1 = Config({})
config2 = Config({})
config1.dataset[1] = 1
print(repr(config1.dataset))
print(repr(config2,dataset))

上述运行结果是

'{1: 1}'
'None'

但如果是这样

share_var = {}
config1 = Config(share_var)
config2 = Config(share_var)
config1.dataset[1] = 1
print(repr(config1.dataset))
print(repr(config2,dataset))

运行结果就会变成:

'{1: 1}'
'{1: 1}'

share_var是可变对象,然而{}是不可变对象,虽然share_var和{}的值一样。

要往更深层次地理解,就需要理解python的命名空间了。

传参和传递可变对象参数需要注意的事情

  1. 如果不是要传引用/指针,去操作对应的内存空间,则传参时注意不要传字典、列表、集合、类或类的实例化对象等类型
  2. 传递可变对象参数时,注意不要传常量{} [] set((, )),最好是在传参前付给一个变量,传参时传这个变量。

懂了原理可能不至于直接传常量,但是有可能出现下面这种情况:

def func1(mutable_object, flag):
    if flag:
        return mutable_object
    else:
        return {}

def func2(mutable_object):
    # something to do with mutable_object
    pass

func2(func1(mutable_object, False))		# 此处func1(mutable_object, False)返回的是{},是一个不可变对象
python注释,快捷键,基础数据类型,运算符,格式化及常用函数1及深浅拷贝 python基础数据类型及常用函数 阅读详情

相关推荐

从理论到实践:TRL去嵌入校准在国产矢量网络分析仪上的应用全解析

本文全面解析了TRL去嵌入校准技术在国产矢量网络分析仪上的应用实践,从核心算法到工程实现。详细介绍了TRL校准的数学原理、国产VNA的程控接口开发、校准件质量评估及测量不确定度控制策略,帮助工程师掌握高频器件测量的关键技术。

tech5的博客 1014

Python数据结构实战决策指南:list dict set tuple选型避坑

Python数据结构不是语法概念,而是影响系统性能、内存占用与并发安全的工程决策核心。理解list的动态数组扩容机制、dict的哈希表查找原理、set的O(1)成员判断特性以及tuple的不可变契约语义,是写出高可靠代码的基础。在真实场景中,list.append()与extend()性能可差百倍,dict.get()比in list快千倍,frozenset让集合成为合法字典键,namedtuple比普通tuple更省内存且语义清晰。本文聚焦高频痛点:日志聚合中的deque替代list、配置管理中的Cha

weixin_34116482的博客 269

VS Code 配置 LaTeX 写作环境完全指南

本文详细介绍了如何在 VS Code 中配置 LaTeX 写作环境,涵盖了从安装必备组件到高级功能的全面指南。首先,用户需要安装 LaTeX 发行版(如 TeX Live 或 MiKTeX)和 VS Code 插件(如 LaTeX Workshop)。接着,通过修改 settings.json 和 keybindings.json 文件,用户可以自定义编译、查看快捷键等基础配置。文章还提供了高效写作技巧,如使用代码片段和多文件项目管理,并介绍了高级功能如反向同步、公式预览和参考文献管理。此外,针对常见问题(

weixin_70043030的博客 1984

python 函数传递参数的多种方法

python中函数根据是否有返回值可以分为四种:无参数无返回值,无参数有返回值,有参数无返回值,有参数有返回值。 Python中函数传递参数的形式主要有以下五种,分别为位置传递,关键字传递,默认值传递,不定参数传递(包裹传递)和解包裹传递。 1.位置传递实例: def fun(a,b,c)   return a+b+c print(f(1,2,3)) 2.关键字传...

2733

踩坑记录:服务商模式下微信小程序支付,为什么必须用子商户的AppID获取openid?

本文深入解析了服务商模式下微信小程序支付必须使用子商户AppID获取openid的技术原因,详细对比了服务商模式与直连模式的关键差异,并提供了正确的配置指南和常见问题解决方案,帮助开发者避免微信支付集成中的常见陷阱。

weixin_28318011的博客 550

无法找到来自源 nvlddmkm 的事件 ID 14 的描述

具体错误是: 无法找到来自源 nvlddmkm 的事件 ID 14 的描述。本地计算机上未安装引发此事件的组件,或者安装已损坏。可以安装或修复本地计算机上的组件。 出现这样错误的原因有很多了,有可能是硬件有可能是软件。由于我是刚配置的电脑,起初非常怀疑是自己组装的问题,折腾了好久,心态爆炸!!!先说我报这样错误的情况,以及解决办法,供后面人参考。 ...

SeventhBlue 6万+

Python指定函数参数和返回值的类型

函数注解本质上是Python语言中特殊的注释语法,可以提供更好的代码可读性和明确度,但并不会进行类型检查。在函数内部,仍然可以传递任何类型的参数和返回任何类型的值。(Function Annotation)来指定函数参数和返回值的类型。函数注解是Python 3引入的一种语法,允许。如果要进行类型检查,可以在函数中使用isinstance或其他类型检查函数来验证函数的参数和返回值是否符合预期类型。来指定函数参数和返回值的类型, 但这并不会影响函数的行为。

weixin_42117918的博客 2480

IST——In-System-Test

安全性是自动驾驶平台的关键特性之一,而这些架构中使用的半导体芯片必须保证ISO 26262标准所要求的功能安全方面。为了监控由于现场缺陷导致的故障,在启动和/或关闭期间会自动运行系统内结构测试。当系统内测试(IST,In-System-Test)架构检测到任何永久性缺陷时,驾驶平台会做出响应,以实现系统的故障安全状态。汽车IC采用高质量测试方法进行筛选,以实现接近零的DPPM(每百万缺陷部件)。即使在这样的高测试标准下,由于环境或操作条件的影响,在系统现场运行过程中仍可能出现可靠性缺陷。

weixin_50518899的博客 3207

python解析命令行参数为dict

主要包含参数的接收、解析与输出。

呆萌的代Ma 358

VTK GPU 加速渲染技术

/ 创建颜色工具// 创建立方体数据// 创建OpenGL映射器(注意使用vtkOpenGLPolyDataMapper而不是常规的vtkPolyDataMapper)// 启用VBO(顶点缓冲对象)// 声明几何体是静态的以获得最佳性能// 创建actor// 创建渲染器、渲染窗口和交互器renderWindow->SetWindowName("VTK自定义着色器示例");// 添加actor到渲染器。

深之JohnChen的专栏 1242

Oracle EBS FA 创建成批增加执行时间长且报错

摘要 Oracle EBS系统在执行"创建成批增"请求时出现长时间运行并报错(ORA-00603和ORA-03114)。

陈显平的专栏-Oracle EBS 174

Python (类型提示)指定参数类型以及参数注解

众所周知,Python 是动态类型语言,运行时不需要指定变量类型。这一点是不会改变的,但是2015年9月创始人 Guido van Rossum 在 Python 3.5 引入了一个类型系统,允许开发者指定变量类型–类型提示(Type Hints)。它的主要作用是方便开发,供IDE 和各种开发工具使用,对代码运行不产生影响,运行时会过滤类型信息。 主要优点如下: 1、易于理解代码 指定函数输入和输出,便于理解代码片段的过程。永远记住你阅读的代码,比你写的代码要多得多。 有了类型提示(Type Hints.

xjcoolice的博客 7万+

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

python基本数据类型--字典(dict)

本文详细介绍了字典的定义方式、访问元素的值、修改元素的值、新增元素、删除元素、清空字典、更新字典、字典的比较方式、身份运算、成员运算等。字典是用{}作为边界逗号作为分隔符,采用键:值一一对应的方式。其中键必须是不可变的数据类型(整型、浮点型、字符串、元组、冻结集合),值可以是任意的python对象,如:{},{1: 2, "a": 5}等等,是可迭代的数据类型,可以被修改。

爆笑蛙的博客 4795

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

Python — List、Set、Tuple、Dictionary之间的区别、参数传递

1、list 列表   有序集合,随时增删。包含的数据类型可以不同:整数、浮点数、字符串、list、tuple、dict、set、bool、空值、常量。   list = [12, 'Yummy', 19.2, [1, 3, 'zhan']] list名为列表,相当于一个数组 list列表是有序的,其中的每个元素都分配一个位置索引,索引值从0开始 lis...

dbsggal90047018的博客 340

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

Python篇---python参数传递

Python函数变量传递机制解析:通过快递类比清晰阐述了两种传递方式。对于不可变类型(数字、字符串等),传递的是值拷贝(复印件),函数内修改不影响原变量;对于可变类型(列表、字典等),传递的是对象引用(仓库地址),函数内修改会影响原变量。文章详细说明了变量在Python中作为标签而非盒子的本质,并对比了参数传递的四种方式(位置、关键字、默认、可变参数)。特别指出了常见陷阱,如默认参数使用可变对象的问题,以及浅拷贝/深拷贝的区别。

在你不想做的时候,正是应该做的时候。 912

Python基础:可变类型与不可变类型彻底搞懂

本文深入解析了Python中可变类型与不可变类型的核心区别。不可变类型(如int、str、tuple)创建后值不能被修改,任何"修改"操作都会创建新对象;而可变类型(如list、dict、set)可以原地修改内容而不改变对象标识。文章通过id()函数验证了这一机制,列举了Python中所有可变和不可变类型,并详细分析了字符串、整数和元组的修改行为。理解这一概念对正确使用Python的赋值、传参和拷贝操作至关重要。

输出倒逼输入,写作驱动成长。 2009

《Python 参数传递机制深度剖析:从引用到拷贝,一篇全搞定》

本文深入解析 Python 的参数传递机制——传递对象引用(pass-by-object-reference)。通过 `id()` 函数验证实参、形参和对象属性共享同一内存地址,揭示“变量是对象的引用”这一核心。重点区分可变对象(list、dict、set)与不可变对象(int、str、tuple)在传参时的不同表现:不可变对象因无法修改而看似“复制”,可变对象则因共享引用而产生“别名副作用”。文章进一步通过“狗玩具箱”案例详细对比直接赋值、浅拷贝和深拷贝三种处理可变对象的方式,并警示避免使用可变对象作为函

qq_73753963的博客 326

python阶段总结(基本三大结构、基本数据类型、函数)

py笔记

sz1125218970的博客 430

Python可变与非可变数据类型

不可变数据类型(数值)在赋值以后, 其中一个值的改变不影响另外一个变量,因为两者指向空间地址不同。

m0_49893661的博客 1252

douyin-downloader:把抖音博主主页的无水印作品批量下载到本地磁盘

你盯着一个博主主页上的 300 条视频,打算用鼠标一条条右键保存?douyin-downloader 是一个用 Python 写的抖音批量下载工具:把主页链接填进配置文件,它会翻完全部作品,跳过的跳过、失败的自动重试,最后按文件夹整理好落盘。 ## douyin-downloader 能替你干哪几件事 先看看它能给你什么,再决定要不要往下装: - 主页作品整页批量落盘 - 已保存的跳过,只做

gitblog_00821的博客 1025

python函数 数据容器

(2)函数的参数。

2401_83837907的博客 1061

python入门篇08- 数据容器, 函数(参数传递) -总结进阶

介绍了几种数据容器 以及相对应的api操作应用场景以及基础小案例python入门篇09- 文件操作,函数, 包及模块的综合案例函数的不同传递方式, 使用更加灵活。

pingzhuyan的博客 397

Python学习笔记——基本类型、函数、输入和输出

常规的函数定义结构如下:函数的声明需要使用def关键字。函数必须拥有一个函数名,且包含参数括号,用于声明。定义参数类型时使用‘:’作为引导符,使用‘->’作为返回值引导符当出现多个参数类型定义时,可以使用‘|’作为分割符cb(a, b)

DRLDER的博客 271

【python】函数二

1122

2503_92107148的博客 52

python学习笔记5--Python函数

Python函数

kyrie_sakura的博客 137
上一篇: 解决缺少API-MS-WIN-CORE-SYNCH-L1-1-0.DLL等一系列DLL的问题
下一篇: 技嘉GA-H97-HD3黑苹果安装+配置windows双系统
tsurara-gb
博客等级 码龄15年 12粉丝 6原创
评论 11
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

tsurara-gb

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值