在学完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

原来的值为1int型对象仍然存在,但我们不能再通过a这个标识符去访问它了(当一个对象没有任何标签或引用指向它时,它就会被自动释放)。如果我们把变量a赋给另一个变量,我们只是给当前内存中对象增加一个“标签”而已:
b = a

综上所述,在Python中变量只是一个标签,一个标识符,它指向内存中的对象。故变量并没有类型,类型是属于对象的,这也是Python中的变量可以被任何类型赋值的原因。

二、可变对象与不可变对象
Python的基本数据类型中,我们知道numbersstringstuples是不可更改的对象,而listdict是可以修改的对象。那么可变与不可变有什么区别呢?看下面示例:

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作为参数传递给函数,这时avar都指向内存中值为1的对象。然后在函数中var = 2时,因为int对象不可改变,于是创建一个新的int对象(值为2)并且令var指向它。而a仍然指向原来的值为1int对象,所以函数没有改变变量a
如下图:

代码2;

def Bar(var):
var.append(1) b = []
print(b)
Bar(b)
print(b)

这段代码把b传递给函数Bar,那么bvar都会指向同一个list类型的对象。因为list对象是可以改变的,函数中使用append在其末尾添加了一个元素,list对象的内容发生了改变,但是bvar仍然是指向这一个list对象,所以变量b的内容也发生了改变。
如下图:

那么Python中参数传递是传值,还是传引用呢?准确的回答:都不是。之所以不是传值,因为没有产生复制,而且函数拥有与调用者同样的对象。而似乎更像是C++的传引用,但是有时却不能改变实参的值。所以只能这样说:对于不可变的对象,它看起来像C++中的传值方式;对于可变对象,它看起来像C++中的按引用传递。

Python学习笔记之函数参数传递 传值还是传引用的更多相关文章

  1. Java学习笔记:具体解释传值和传引用

    传值和传引用 When you're passing primitives into a method ,you get a distinct copy of the primitive. When ...

  2. Python学习笔记之函数

    这篇文章介绍有关 Python 函数中一些常被大家忽略的知识点,帮助大家更全面的掌握 Python 中函数的使用技巧 1.函数文档 给函数添加注释,可以在 def 语句后面添加独立字符串,这样的注释被 ...

  3. java 函数形参传值和传引用的区别

    java方法中传值和传引用的问题是个基本问题,但是也有很多人一时弄不清. (一)基本数据类型:传值,方法不会改变实参的值. public class TestFun { public static v ...

  4. Python学习笔记7-把函数当参数传递、指定可变参数

    把函数当参数传递 # 函数参数传递 # 面向对象编程就是把对象传来传去 # 面向函数编程就是把函数传来传去 def mytest(num): return num * 2 # # 不光可以传递变量,还 ...

  5. Python学习笔记 - day6 - 函数

    函数 函数在编程语言中就是完成特定功能的一个词句组(代码块),这组语句可以作为一个单位使用,并且给它取一个名字.可以通过函数名在程序的不同地方多次执行(这叫函数的调用).函数在编程语言中有基本分为:预 ...

  6. 小甲鱼:Python学习笔记003_函数

    >>> # 函数>>> def myFirstFunction(params1,params2...): print("这是我的第一个函数!") ...

  7. Python学习笔记:函数详解(下)

    本文介绍:高阶函数,嵌套函数,以及由前面两个组成的装饰器 一.高阶函数:以下两种情况都是高阶函数   1.将函数名当成参数传递给另外一个函数(作用:不修改被传递函数源代码就可以添加新功能): impo ...

  8. python 参数传递 传值还是传引用

    个人推测结论: 可变对象传引用,不可变对象传值 python里的变量不同于c中地址储值模型 a=100 b=100 print(id(a),id(b),a==b,a is b) #8790877986 ...

  9. php函数形参传值与传引用

    传值 ------------------------------------------------- function example( $m ){     $m = $m * 5 + 10;   ...

随机推荐

  1. 如何在 Linux 上永久挂载一个 Windows 共享

    导读 如果你已经厌倦了每次重启 Linux 就得重新挂载 Windows 共享,读读这个让共享永久挂载的简单方法. 在 Linux 上和一个 Windows 网络进行交互从来就不是件轻松的事情.想想多 ...

  2. Java反序列化漏洞的挖掘、攻击与防御

    一.Java反序列化漏洞的挖掘 1.黑盒流量分析: 在Java反序列化传送的包中,一般有两种传送方式,在TCP报文中,一般二进制流方式传输,在HTTP报文中,则大多以base64传输.因而在流量中有一 ...

  3. 【BZOJ4598】[Sdoi2016]模式字符串 树分治+hash

    [BZOJ4598][Sdoi2016]模式字符串 Description 给出n个结点的树结构T,其中每一个结点上有一个字符,这里我们所说的字符只考虑大写字母A到Z,再给出长度为m的模式串s,其中每 ...

  4. iOS如何让主界面不显示NavigationBar

    这个问题曾经困扰过我.现在我给出正解.- (void)viewWillAppear:(BOOL)animated {    [super viewWillAppear:animated]; [self ...

  5. 透明 Transparent connections through HTTP proxies.

    透明语境: 5.7层模型中数据链路层:透明传输: 谈谈如何使用Netty开发实现高性能的RPC服务器 - Newland - 博客园 http://www.cnblogs.com/jietang/p/ ...

  6. 让网站全面支持v4/v6 HTTP、HTTPS、HTTP/2最简单方法是增加Nginx反向代理服务器

    bg6cq/nginx-install: nginx install script https://github.com/bg6cq/nginx-install [原创]step-by-step in ...

  7. centos下vsftpd不能显示文件,不能创建文件及文件夹

    centos下vsftpd登录正常,但不能显示文件,不能创建文件及文件夹 这是由于selinux的机制 通过命令 [root@localhost www]# getsebool -a|grep ftp ...

  8. 剑指Offer——把字符串转换成整数

    题目描述: 将一个字符串转换成一个整数,要求不能使用字符串转换整数的库函数. 数值为0或者字符串不是一个合法的数值则返回0   输入描述: 输入一个字符串,包括数字字母符号,可以为空 输出描述: 如果 ...

  9. JS获取当前网页大小以及屏幕分辨率等

    网页可见区域宽:document.body.clientWidth 网页可见区域高:document.body.clientHeight 网页可见区域宽:document.body.offsetWid ...

  10. Python 类型和对象(转)

    译文:http://wiki.woodpecker.org.cn/moin/PyTypesAndObjects 原文:http://www.cafepy.com/article/python_attr ...