从内存管理的角度来看,Python语言的变量和参数传递情况解析

news2024/11/28 11:34:10

从内存管理的角度来看,Python语言的变量和参数传递情况解析

概述

从内存管理的角度来看,Python中的变量和参数传递有一些特点:

☆ 变量是对象的引用:在Python中,变量实际上是对象的引用,而不是对象本身。当你给一个变量赋值时,实际上是将变量指向了一个对象。这意味着变量可以指向不同类型的对象,并且可以在程序中随时改变指向的对象。

☆ 引用计数:Python使用引用计数来管理内存。每个对象都有一个引用计数,表示有多少个变量引用了该对象。当引用计数为0时,对象将被自动回收。当一个变量不再引用一个对象时,引用计数会减少。当引用计数为0时,对象的内存将被释放。

☆ 对象的可变性:Python中的对象分为可变对象和不可变对象。可变对象(如列表、字典)的值可以被修改,而不可变对象(如整数、字符串、元组)的值不能被修改。这意味着如果你修改了一个可变对象,那么所有引用这个对象的变量都会受到影响。

☆ 参数传递方式:在Python中,函数的参数传递是按值调用(call by value) 来传递的(其中的 值 始终是对象的 引用 而不是对象的值)——实际上,按对象引用调用(call by object reference)调用这种说法更好。对于不可变对象(如整数、字符串、元组),由于它们的值不能被改变,所以函数内部对这些对象的修改实际上是创建了一个新的对象。因此,函数内部的修改不会影响到函数外部的实际参数。对于可变对象(如列表、字典),由于它们的值可以被改变,所以函数内部对这些对象的修改会直接改变原始对象的值。因此,函数内部的修改会影响到函数外部的实际参数。

Python语言的变量和赋值情况

Python语言中,所有的 数据 都被称之为 对象。

每个整数、小数、字符串,后面要学的 字典、元组、列表 等, 都是对象。数据对象。

编程语言为了方便操作数据对象,也需要给对象起一个名字,称之为 变量名 , 有时也简称 变量。

Python中的变量,就是 对象的名称。

Python中,名称 用于指代对象。 名称是通过名称绑定操作来引入的。

【见官方文档 命名与绑定

https://docs.python.org/zh-cn/3/reference/executionmodel.html#naming-and-binding

提示:在Python的官方文档中更多地使用了“名称”(name)这个术语来。但是在实际的编码和交流中,人们也常常使用“变量”(variable)这个术语来描述Python中的名称。】

Python 是一门动态类型的语言,所以我们无须预先声明变量类型,直接对变量赋值即可。

可以使用赋值语句来创建变量并使其引用一个数据。当一个变量表示存储器中的某个值时,也称这个变量引用(reference)了这个值。

赋值语句的基本格式是:

Variable = expression

等号(=)称为赋值运算符(assignment operator)。在这个基本格式中,variable 是变量名,expression 是一个值,或者能够产生一个值的代码。赋值语句执行结束后,位于等号左边的变量将引用位于等号右边的值。

提示:在给变量赋值之前是不能使用变量的。如果在变量被赋值之前就对它进行某种操作,如打印它,将导致一个错误。

【注意: Python 语言中的变量与大多数其他编程语言中的变量的工作方式不同。在大多数编程语言中,变量是保存值的内存位置。在这些编程语言中,当给变量赋值时,该值保存在变量的内存位置。而在 Python 语言中,变量是一个内存位置,它保存另一个内存位置的地址。将值赋给 Python 变量时,该值将存储在与该变量分离的内存位置。变量保存的是保存值的内存位置的地址。这就是为什么在 Python 中,不说变量“保存”一个值,而说变量“引用”一个变量。或者说,Python 中变量是代表存储在计算机存储器中的某个值的名称。】

变量之所以称为“变量”,是因为在程序执行过程中它们可以引用不同的值。下面就看看Python 中变量的赋值和再赋值情况。

创建了一个名为 dollars 的变量,并将 2.75 赋值给它

Dollars = 2.75

给变量 dollars 赋以一个新值99.95,当给变量 dollars 赋以一个新值99.95时,虽然旧值 2.75 依然保存在计算机的存储器中,但是因为没有变量引用它,所以这个值已不能再被使用。参见下图:

注意,当存储器中的值不再被变量引用时,Python 解释器将通过所谓的垃圾收集机制来进行处理,自动地将它们移出存储器。

【在python中,变量保存的是对象(值)的引用,id()函数可以获取变量在内存中的地址。在Python中,值可以放在内存的某个位置(地址),变量用于引用它们,给变量赋一个新值,原值不会被新值覆盖,变量只是引用了新值。顺便说明,Python的垃圾回收机制会自动清理不再被用到的值,所以不用担心计算机内存中充满被“丢弃”的无效的值。】

一定要牢记:在 Python 语言中,变量仅仅是引用存储器中某个数据的名字,并且可以引用任何类型的数据项。

x = 99 语句创建了名为 x 的变量,并赋给它 int 型的值 99。

将一个字符串 'Take me to your leader'赋值给变量 x时,变量 x 不再引用一个 int 型数据,而是引用字符串 'Take me to your leader'。

下面再看看这种情况:

a = 10

b = a

在上述的例子中,我们声明了一个变量 a,其值为 10,然后将 b 也指向 a,这是在内存中的布局是这样的,变量 a 和 b 会指向同一个对象 10,而不是给 b 重新生成一个新的对象。

当执行完 a = a + 10 后,因为整数是不可变对象,所以并不会将 10 变成 20,而是生成一个新的对象 20 ,然后 a 会指向这个新的对象。b 还是指向旧对象 10。

Python 允许你同时为多个变量赋值。例如:

a = b = c = 10

以面示例,创建一个整型对象,值为 10,从后向前赋值,三个变量被赋予相同的数值。

您也可以为多个对象指定多个变量。例如:

a, b, c = 10, 20, " hello"

以面示例,两个整型对象 10 和 20 的分配给变量 a 和 b,字符串对象 “hello” 分配给变量 c。

在Python中的参数传递情况

要讲清在Python中函数的参数传递,需要从Python中函数是什么讲起。

在Python中,函数是一种组织代码的方式,它将一段程序代码封装起来,以便于重复使用。函数可以接收输入参数,并返回一个或多个结果。这种封装可以使代码更加清晰、易读,也有助于代码的重用。Python提供了许多内置函数,如print()、len()等,可以直接使用。编程人员还可以自定义函数。自定义图示如下:

Python中的函数定义使用def关键字,后跟函数名、括号()和冒号。括号中可以放置函数的参数,参数之间用逗号分隔。函数的主体部分在冒号后的缩进块中定义。Python中定义函数语法如下:

def 函数名(参数列表):

    函数体

函数体由缩进的代码块组成。Python的函数体包括:

函数体包括以下几个部分:

文档字符串(docstring):文档字符串是可选的,用于描述函数的作用、参数、返回值等信息。它位于函数定义的第一行或第二行,使用三引号('''或""")括起来。文档字符串可以通过help()函数或在交互式环境中使用__doc__属性来访问。

语句(statements):函数体中可以包含任意数量的语句,用于执行具体的任务。这些语句可以是赋值语句、条件语句、循环语句等,根据函数的需求编写。

返回表达式(return expression):函数可以通过return语句返回一个值。返回值是可选的,如果没有return语句或者return后面没有表达式,函数将返回None。当函数执行到return语句时,函数将立即结束,并将返回值传递给调用函数的地方。

下面介绍python参数传递

python官方文档的说法【https://docs.python.org/zh-cn/3/tutorial/controlflow.html#defining-functions 】实参是使用 按值调用(call by value) 来传递的(其中的 值 始终是对象的 引用 而不是对象的值)——实际上,按对象引用调用(call by object reference)调用这种说法更好。具体来说:

如果传入的参数是不可变类型(如数字、字符串、元组),那么在函数体内修改参数的值,并不会影响到原来的变量。因为不可变类型的变量实际上是值的引用,当你试图改变变量的值时,相当于是在创建新的对象。例如:

def change_number(num):
    num = 100

x = 10
change_number(x)
print(x)  # 输出:10

在上面的例子中,尽管在函数内部num的值被改变了,但是原变量x的值并没有改变。参见下图:

如果传入的参数是可变类型(如列表、字典),那么在函数体内修改参数的值,会影响到原来的变量。因为可变类型的变量存储的是一个地址,当你试图改变变量的值时,实际上是在改变这个地址所指向的内容。例如:

def change_list(lst):
    lst.append(100)

x = [1, 2, 3]
change_list(x)
print(x)  # 输出:[1, 2, 3, 100]

在上面的例子中,函数内部对参数lst的修改影响到了原变量x的值。参见下图:

附录

Python变量的认识理解 https://blog.csdn.net/cnds123/article/details/116768499 
python函数 https://blog.csdn.net/cnds123/article/details/108179769

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1160214.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Mysql数据库 7.SQL语言 关联关系

关联关系介绍 Mysql是一个关系型数据库,不仅可以存储数据,还可以维护数据与数据之间的关系——通过在数据表中添加字段建立约束 数据与数据之间的关联关系: 1.一对一关联 2.一对多关联 3.多对一关联 4.多对多关联 一个表的外键对应另一…

2023年【道路运输企业主要负责人】考试技巧及道路运输企业主要负责人复审模拟考试

题库来源:安全生产模拟考试一点通公众号小程序 2023年【道路运输企业主要负责人】考试技巧及道路运输企业主要负责人复审模拟考试,包含道路运输企业主要负责人考试技巧答案和解析及道路运输企业主要负责人复审模拟考试练习。安全生产模拟考试一点通结合…

leetcode:1446. 连续字符(python3解法)

难度:简单 给你一个字符串 s ,字符串的「能量」定义为:只包含一种字符的最长非空子字符串的长度。 请你返回字符串 s 的 能量。 示例 1: 输入:s "leetcode" 输出:2 解释:子字符串 &q…

虹科资讯 | 10月智能制造行业动态回顾

文章来源:虹科工业控制 阅读原文:https://mp.weixin.qq.com/s/0jR_QgmR6tmrRoTFAo8mFw 10月,虹科与PLCopen合作开展IEC 61131-3培训,目前正在火热报名中;人工智能领域的迅猛发展引起了智能制造业的广泛关注&#xff…

Flink1.18新特性生产环境应用的重点解读!

大家好,我是你们的群主王知无呀。 Flink 1.18已经于近期发布了。在这个新版本中新增了很多新的功能和特性。在这些特性中,有一些是生产环境非常重要的能力,大家在使用过程中可以重点参考和了解其中的原理。 算子级别状态保留时间TTL设置 首先…

CSS3媒体查询与页面自适应

2017年9月,W3C发布媒体查询(Media Query Level 4)候选推荐标准规范,它扩展了已经发布的媒体查询的功能。该规范用于CSS的media规则,可以为文档设定特定条件的样式,也可以用于HTML、JavaScript等语言。 1、媒体查询基础 媒体查询…

苹果AirTag平替产品选择,国内外支持苹果Find My芯片功耗全面对比

2021年4月20,苹果在春季产品发布会上推出了全新的产品类型- AirTag,将哆啦A梦的追踪徽章带到了现实。这个小产品当年并没有像其它苹果新品那样一朝爆红。随着年轮缓缓而坚定地前行, AirTag也缓缓而坚定地前行,并被越来越多的人接受和喜欢。 深入思考AirTag背后的产品逻辑和实现…

双11价格博弈之下,电商大战走向何方?

第十五个双11,电商平台内卷越发激烈。 10月18日,短视频平台快手迫不及待地打响第一枪,随后拼多多、淘宝天猫、京东纷纷启动双11。 不过,和以往不同的是,今年双11是随着“高端商战”一起拉开帷幕的。从京东采销喊话头…

Web安全系列——注入攻击

文章首发公众号: 海天二路搬砖工 前言 在Web应用程序开发中,防SQL注入最基本的安全防护要求了。其实除了SQL注入, 还有很多其他的注入攻击方式。注入攻击是最常见的Web应用攻击方式之一。 本文将介绍注入攻击的概念、种类、原理&#xff0…

删除链表的倒数第n个节点(C++解法)

题目 给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。 示例 1: 输入:head [1,2,3,4,5], n 2 输出:[1,2,3,5]示例 2: 输入:head [1], n 1 输出:[]示例 3&#…

Linux 服务器 Oracle19C安装

原文:【精选】Oracle | CentOS7安装Oracle19c数据库(RPM包)_oracle-database-preinstall-19c-1.0-1.el7.x86_64.rp_Thorolds Deer的博客-CSDN博客 下载 第一个软件包:Oracle Database 19c Download for Linux x86-64 第二个包:Oracle Linux 7 (x86_64) Latest | Oracle,…

【Springboot】集成Swagger

引入依赖 <dependency><groupId>io.springfox</groupId><artifactId>springfox-boot-starter</artifactId><version>3.0.0</version> </dependency> 浏览器 启动项目后 在浏览器中输入地址 localhost:端口号/swagger-ui/ 使…

Android各版本对应的SDK及JDK版本要求

1、Android Gradle 插件版本说明 | Android 开发者 | Android Developers 2、 3、Android Gradle 插件 7.3.0&#xff08;2022 年 9 月&#xff09; | Android 开发者 | Android Developers 4、 5、参考 Android中Gradle版本和Gradle插件版本 - 简书

深度学习实战:基于TensorFlow与OpenCV的手语识别系统

文章目录 写在前面基于TensorFlow与OpenCV的手语识别系统安装环境一、导入工具库二、导入数据集三、数据预处理四、训练模型基于CNN基于LeNet5基于ResNet50 五、模型预测基于OpenCV 写在后面 写在前面 本期内容&#xff1a;基于TensorFlow与OpenCV的手语识别系统 实验环境&…

物联网AI MicroPython传感器学习 之 MFRC522 RFID射频IC卡感应模块

学物联网&#xff0c;来万物简单IoT物联网&#xff01;&#xff01; 一、产品简介 MFRC522是应用于13.56MHz非接触式通信中高集成度的读写卡芯片&#xff0c;其特点低电压、低成本、体积小的非接触式读写芯片。MFRC522支持MIFARE系列更高速的非接触式通信&#xff0c;双向数据…

如何理解傅里叶变换?

当提到什么是傅里叶变换&#xff1f; 大家的回答一般是&#xff1a;将信号从时域转化到频域&#xff1f; 那为什么要转换到频域呢&#xff1f; 因为在频域可将一些信号分离。 为什么转换到频域就可分离呢&#xff1f;好像不会回答了。 实际上&#xff0c;从线性代数的角度…

Spring面试题:(二)基于xml方式的Spring配置

xml配置Bean的常见属性 id属性 name属性 scope属性 lazy-init属性 init-method属性和destroy属性 initializingBean方法 Bean实例化方式 ApplicationContext底层调用BeanFactory创建Bean&#xff0c;BeanFactory可以利用反射机制调用构造方法实例化Bean&#xff0c;也可采用工…

【嵌入式开发学习】__改了一行代码,数组遍历耗时从10.3秒降到了0.5秒!

目录 前言 两个简单的测试程序 1. array1.c 对数组按行进行访问 2. array2.c 对数组按列进行访问 ​编辑 3. 编译运行&#xff0c;并用 time 命令统计一下运行时间&#xff1a; 重要说明 存储金字塔 局部性原理 1. 时间局部性 2. 空间局部性 高速缓存 - Cache Cache…

Word 将文档中的【第几条】批量加粗

目录预览 一、问题描述二、解决方案三、参考链接 一、问题描述 我要制作一份文档&#xff0c;关于法律条文的&#xff0c;然后需要将条文中的【第几条】字样进行加粗表示&#xff0c;格式刷是不可能格式刷的&#xff0c;这明显不适合此种批量的操作&#xff0c;浪费事件。所以…

matplotlib入门-基金走势图

一、matplotlib简介 matplotlib是一个Python 2D绘图库&#xff0c;开发者仅需要几行代码就可以生成曲线图、柱状图、散点图甚至动画。需要另外安装&#xff0c;一条命令搞定。 pip install matplotlib 它的绘图接口在matplotlib.pyplot模块中&#xff0c;pyplot提供和MATLIB…