建设企业网站对公,邢台123招聘信息最新招聘信息网,昆汀的室内设计案例,珠海市品牌网站建设公司文章目录 版本前言形参和实参值传递和引用传递Python 变量存储值语义和引用语义值语义引用语义 探讨 Python 值传递和引用传递不可变#xff08;immutable#xff09;类型可变#xff08;mutable#xff09;类型案例一案例二 拓展#xff1a;不可变类型真的不可变#xf… 文章目录 版本前言形参和实参值传递和引用传递Python 变量存储值语义和引用语义值语义引用语义 探讨 Python 值传递和引用传递不可变immutable类型可变mutable类型案例一案例二 拓展不可变类型真的不可变总结个人简介 版本
Python 3.9
前言
在编程语言中值传递pass by value和引用传递pass by reference是两个重要的概念。它们涉及到变量在函数调用中的传递方式对于理解函数调用和参数传递的机制至关重要。在本文中我们将深入探讨 Python 中的值传递和引用传递并通过代码示例进行说明。
形参和实参
我们先了解一点前置知识形参和实参先说概念形参出现在函数定义中在整个函数体内都可使用离开函数体则不可使用。实参出现在主调函数中进入被调函数后不能使用。
def func(param):# 这里 param 为形参print(param)if __name__ __main__:# 这里的 a 就是实参a 1func(a)值传递和引用传递
我们先了解一下值传递和引用传递的概念值传递是指在调用方式时将实参的值拷贝一份给形参对形参的修改不影响实参。引用传递也叫地址传递指在调用方法时将实参的地址传递给形参对形参的修改将影响实参的值即传递的是实参的内存地址。
Python 变量存储
对于python而言python的一切变量都是对象变量的存储采用了引用语义的方式存储的只是一个变量的值所在的内存地址而不是这个变量的只本身。 代码实测
a 1
print(f变量a的地址{id(a)})b 1
print(f变量b的地址{id(b)})b 2
print(f变量b的地址{id(b)})上面实例输出如下
变量a的地址2483649669424
变量b的地址2483649669424
变量b的地址2483649669456从实际用例我们可以看出a、b 1 时这里底层为了性能考虑指向相同的内存当 b 发生改变时发生写时复制b 指向了新的内存地址。
值语义和引用语义
值语义
值语义是指将变量赋值为另一个变量时会复制变量的值而不是引用原始值所在的内存地址。如 Java 的基本数据类型。
引用语义
引用语义是指将变量赋值为另一个变量时实际上是将变量指向同一个对象的内存地址而不是复制对象的值。如 Java 的引用数据类型、Python 值存储。
探讨 Python 值传递和引用传递
了解完上面的一些基本概念后我们从可变mutable和不可变immutable两种类型来探讨 Python 值传递和引用传递
不可变immutable类型
不可变变量的值一旦创建就不能被修改。如果你尝试修改一个不可变对象的值Python 将会创建一个新的对象。Python 中的不可变对象包括整数int、浮点数float、字符串str、元组tuple等。先简单看一个下面的例子
def modify_value(x):print(f变量x修改前地址{id(x)})x x 10print(f变量x修改后地址{id(x)})print(函数内部修改后的值为:, x)# 调用函数
value 5
print(f变量value地址{id(value)})
modify_value(value)
print(函数外部原始值为:, value)在这个示例中我们定义了一个函数 modify_value它接受一个参数 x。在函数内部我们对 x 的值进行修改并打印出修改后的值。然后我们调用函数传递了一个值为 5 的参数 value。运行以上代码将会输出
变量value地址1886976960944
变量x修改前地址1886976960944
变量x修改后地址1886976961264
函数内部修改后的值为: 15
函数外部原始值为: 5可以看到尽管在函数内部修改了形式参数 x 的值但并没有影响到函数外部实际参数 value 的值而发生了写时复制。
可变mutable类型
可变变量的值可以在原地修改而不会创建一个新的对象。Python 中的可变对象包括列表list、字典dict、集合set等。我们以 list 类型为例
案例一
def modify_list(list):print(f变量list地址{id(list)})list[2] 4print(f变量list修改地址{id(list)})print(函数内部修改后的列表为:, list)# 调用函数
my_list [1, 2, 3]
print(f变量my_list地址{id(my_list)})
modify_list(my_list)
print(函数外部原始列表为:, my_list)输出如下
变量my_list地址2115249727936
变量list地址2115249727936
变量list修改地址2115249727936
函数内部修改后的列表为: [1, 2, 4]
函数外部原始列表为: [1, 2, 4]案例二
def modify_list(list):print(f变量list地址{id(list)})list [6, 6, 6]print(f变量list修改地址{id(list)})print(函数内部修改后的列表为:, list)# 调用函数
my_list [1, 2, 3]
print(f变量my_list地址{id(my_list)})
modify_list(my_list)
print(函数外部原始列表为:, my_list)输出如下
变量my_list地址2141908331136
变量list地址2141908331136
变量list修改地址2141908181248
函数内部修改后的列表为: [6, 6, 6]
函数外部原始列表为: [1, 2, 3]看完上面的两个案例你是否有些许疑惑案例一修改了函数外的原始值案例二未修改函数外的原始值下面我们用图解来解释一下上面发生了什么 从图解中我们可以清晰的看到在案例一和案例二中函数传递了 my_list 地址的拷贝值案例一中持有数组的内存地址因此成功修改了原数组元素案例二中 list 的内存地址修改为新的数组内存地址并没有修改原数组的值。通过对可变mutable和不可变immutable两种类型的函数传递的分析我们可以知道由于 Python 中一切皆对象的特性实际传递给函数的都是内存地址的拷贝从表现上来说我们可以说 Python 中都是值传递了解过 Java 的同学会发现这里和 Java 的引用类型原理一致。
拓展不可变类型真的不可变
上面我们提到了可变类型和不可变类型不可变类型真的是不可变的我们来看下面的案例
arr (1, 2, [4, 4])print(f元组修改前{arr})
arr[2][0] 2
print(f元组修改后{arr})
输出结果
元组修改前(1, 2, [4, 4])
元组修改后(1, 2, [2, 4])上面的案例中不可变类型出现了变化这个是 bug ? 其实并不是不可变类型的不可变指的是组成的元素是不可变的在上面的案例 arr 元组中存储的是对应的内存地址而不可变指的是内存地址和指向无法改变但如果内存地址指向的是可变类型比如数组那么元素内部是可变的。
总结
本文以值传递、引用传递的基本概念、以及 Python 变量存储为基础从可变mutable和不可变immutable两种类型来分析 Python 值传递和引用传递的真相通过充足的案例分析我们发现Python变量 和 Java 引用类型类似只存在值传递。
个人简介 你好我是 Lorin 洛林一位 Java 后端技术开发者座右铭Technology has the power to make the world a better place. 我对技术的热情是我不断学习和分享的动力。我的博客是一个关于Java生态系统、后端开发和最新技术趋势的地方。 作为一个 Java 后端技术爱好者我不仅热衷于探索语言的新特性和技术的深度还热衷于分享我的见解和最佳实践。我相信知识的分享和社区合作可以帮助我们共同成长。 在我的博客上你将找到关于Java核心概念、JVM 底层技术、常用框架如Spring和Mybatis 、MySQL等数据库管理、RabbitMQ、Rocketmq等消息中间件、性能优化等内容的深入文章。我也将分享一些编程技巧和解决问题的方法以帮助你更好地掌握Java编程。 我鼓励互动和建立社区因此请留下你的问题、建议或主题请求让我知道你感兴趣的内容。此外我将分享最新的互联网和技术资讯以确保你与技术世界的最新发展保持联系。我期待与你一起在技术之路上前进一起探讨技术世界的无限可能性。 保持关注我的博客让我们共同追求技术卓越。