Python学习笔记之函数参数传递 传值还是传引用
在学完Python
函数那一章节时,很自然的的就会想到Python
中函数传参时传值呢?还是传引用?或者都不是?
在回答上面的问题之前我们先来看看下面的代码:
代码1:
- def foo(var):
- var = 2
- print(var) #output: 2
- a = 1
- foo(a)
- print(a) #output: 1
恩,看似是值传递
代码2:
- def bar(var):
- var.append(1)
- b = []
- print(b) #output:[]
- bar(b)
- print(b) #output:[1]
应该是引用传递?有点奇怪吧,为了弄清楚这个问题,我们先来了解一下Python
中变量与对象的关系。
一、变量和对象
我们首先要知道Python
中的“变量”与C/C++
中“变量”是不同的。
在C/C++
中,当你初始化一个变量时,就是声明一块存储空间并写入值。相当于把一个值放入一个盒子里:
int a = 1;
现在a
盒子里放了一个整数1
,当给变量a
赋另外一个值时会替换盒子a
里面的内容:
a = 2;
当你把变量a
赋给另外一个变量时,会拷贝a
盒子中的值并放入一个新的“盒子”里:
int b = a;
但是
在Python
中,一个变量可以说是内存中的一个对象的“标签”或“引用”:
a = 1
现在变量a
指向了内存中的一个int
型的对象(a
相当于对象的标签)。如果给a
重新赋值,那么“标签” a
将会移动并指向另一个对象:
a = 2
原来的值为1
的int
型对象仍然存在,但我们不能再通过a
这个标识符去访问它了(当一个对象没有任何标签或引用指向它时,它就会被自动释放)。如果我们把变量a
赋给另一个变量,我们只是给当前内存中对象增加一个“标签”而已:
b = a
综上所述,在Python
中变量只是一个标签,一个标识符,它指向内存中的对象。故变量并没有类型,类型是属于对象的,这也是Python
中的变量可以被任何类型赋值的原因。
二、可变对象与不可变对象
在Python
的基本数据类型中,我们知道numbers
、strings
和tuples
是不可更改的对象,而list
、dict
是可以修改的对象。那么可变与不可变有什么区别呢?看下面示例:
- a = 1 # a指向内存中一个int型对象
- a = 2 # 重新赋值
当将a
重新赋值时,因为原来值为1
的对象是不能改变的,所以a
会指向一个新的int
对象,其值为2
。(如下面的图示)
示例2
- list1 = [1, 2] # list1指向内存中一个list类型的对象
- list1[0] = 2 # 重新赋值list1中第一个元素
因为list
类型是可以改变的,所以第一个元素变更为2
。更确切的说,list1
的第一个元素是int
型,重新赋值时一个新的int
对象被指定给第一个元素,但是对于list1
来说,它所指的列表型对象没有变,只是列表的内容(其中一个元素)改变了。如下图:
现在我们再来看看开始那两段代码:
- def foo(var):
- var = 2
- print(var)
- a = 1
- foo(a)
- print(a)
上面这段代码把a
作为参数传递给函数,这时a
和var
都指向内存中值为1
的对象。然后在函数中var = 2
时,因为int
对象不可改变,于是创建一个新的int
对象(值为2
)并且令var
指向它。而a
仍然指向原来的值为1
的int
对象,所以函数没有改变变量a
。
如下图:
代码2;
- def Bar(var):
- var.append(1)
- b = []
- print(b)
- Bar(b)
- print(b)
这段代码把b
传递给函数Bar
,那么b
和var
都会指向同一个list
类型的对象。因为list
对象是可以改变的,函数中使用append
在其末尾添加了一个元素,list
对象的内容发生了改变,但是b
和var
仍然是指向这一个list
对象,所以变量b
的内容也发生了改变。
如下图:
那么Python
中参数传递是传值,还是传引用呢?准确的回答:都不是。之所以不是传值,因为没有产生复制,而且函数拥有与调用者同样的对象。而似乎更像是C++
的传引用,但是有时却不能改变实参的值。所以只能这样说:对于不可变的对象,它看起来像C++中的传值方式;对于可变对象,它看起来像C++中的按引用传递。
Python学习笔记之函数参数传递 传值还是传引用的更多相关文章
- Java学习笔记:具体解释传值和传引用
传值和传引用 When you're passing primitives into a method ,you get a distinct copy of the primitive. When ...
- Python学习笔记之函数
这篇文章介绍有关 Python 函数中一些常被大家忽略的知识点,帮助大家更全面的掌握 Python 中函数的使用技巧 1.函数文档 给函数添加注释,可以在 def 语句后面添加独立字符串,这样的注释被 ...
- java 函数形参传值和传引用的区别
java方法中传值和传引用的问题是个基本问题,但是也有很多人一时弄不清. (一)基本数据类型:传值,方法不会改变实参的值. public class TestFun { public static v ...
- Python学习笔记7-把函数当参数传递、指定可变参数
把函数当参数传递 # 函数参数传递 # 面向对象编程就是把对象传来传去 # 面向函数编程就是把函数传来传去 def mytest(num): return num * 2 # # 不光可以传递变量,还 ...
- Python学习笔记 - day6 - 函数
函数 函数在编程语言中就是完成特定功能的一个词句组(代码块),这组语句可以作为一个单位使用,并且给它取一个名字.可以通过函数名在程序的不同地方多次执行(这叫函数的调用).函数在编程语言中有基本分为:预 ...
- 小甲鱼:Python学习笔记003_函数
>>> # 函数>>> def myFirstFunction(params1,params2...): print("这是我的第一个函数!") ...
- Python学习笔记:函数详解(下)
本文介绍:高阶函数,嵌套函数,以及由前面两个组成的装饰器 一.高阶函数:以下两种情况都是高阶函数 1.将函数名当成参数传递给另外一个函数(作用:不修改被传递函数源代码就可以添加新功能): impo ...
- python 参数传递 传值还是传引用
个人推测结论: 可变对象传引用,不可变对象传值 python里的变量不同于c中地址储值模型 a=100 b=100 print(id(a),id(b),a==b,a is b) #8790877986 ...
- php函数形参传值与传引用
传值 ------------------------------------------------- function example( $m ){ $m = $m * 5 + 10; ...
随机推荐
- 用VS不同版本打开项目,报错:MS Build Error MSB4019: Microsoft.WebApplication.targets was not found
本例是在用VS2008打开项目是报错 未找到C:\Program Files\MSBuild\Microsoft\VisualStudio\V10.0 In the last article Buil ...
- 【BZOJ1135】[POI2009]Lyz 线段树
[BZOJ1135][POI2009]Lyz Description 初始时滑冰俱乐部有1到n号的溜冰鞋各k双.已知x号脚的人可以穿x到x+d的溜冰鞋. 有m次操作,每次包含两个数ri,xi代表来了x ...
- FormsAuthentication 使用指南
配置安全鉴别 鉴别是指鉴定来访用户是否合法的过程.ASP.NET Framework支持三种鉴别类型: Windows鉴别: NET Passport鉴别: Forms鉴别. 对于某一特定的应用程序, ...
- 在任何mac上用u盘安装OSX和Windows10双系统的方法(支持老电脑、不用Bootcamp)
Win10是微软主推的,兼容性做的还不错,安装工具做的适应性好. 而且很多Mac机上的Bootcamp不支持u盘安装. 1.先安装OSX,一般电脑自带(建议升级到最新版).如果装了新的ssd,重新安装 ...
- Python中的Numpy
引用Numpy import numpy as np 生成随机数据 # 200支股票 stock_cnt = 200 # 504个交易日 view_days = 504 # 生成服从正态分布:均值期望 ...
- 剑指Offer——第一个只出现一次的字符位置
题目描述: 在一个字符串(1<=字符串长度<=10000,全部由字母组成)中找到第一个只出现一次的字符,并返回它的位置. 分析: 用一个数组统计每个字符出现的次数. 再次扫描数组,如果找到 ...
- ntopng基础
当你在本地网络监控网络流量,根据流量大小.监控平台/接口.数据库类型等等,可以有许多不同的选择.ntopng是一套开源(遵循GPLv3协议)网络流量分析解决方案,提供基于web界面的实时网络流量监控. ...
- 【chainer框架】【pytorch框架】
教程: https://bennix.github.io/ https://bennix.github.io/blog/2017/12/14/chain_basic/ https://bennix.g ...
- Git 使用vi或vim
1.vi & vim 有两种工作模式: (1) 命令模式:接受.执行 vi & vim 操作命令的模式,打开文件后的默认模式: (2) 编辑模式:对打开的文件内容进行 增.删.改 操作 ...
- Flume 1.7 源代码分析(四)从Source写数据到Channel
Flume 1.7 源代码分析(一)源代码编译 Flume 1.7 源代码分析(二)总体架构 Flume 1.7 源代码分析(三)程序入口 Flume 1.7 源代码分析(四)从Source写数据到C ...