首先还是应该科普下函数参数传递机制,传值和传引用是什么意思?

函数参数传递机制问题在本质上是调用函数(过程)和被调用函数(过程)在调用发生时进行通信的方法问题。基本的参数传递机制有两种:值传递和引用传递。

值传递(passl-by-value)过程中,被调函数的形式参数作为被调函数的局部变量处理,即在堆栈中开辟了内存空间以存放由主调函数放进来的实参的值,从而成为了实参的一个副本。值传递的特点是被调函数对形式参数的任何操作都是作为局部变量进行,不会影响主调函数的实参变量的值。

引用传递(pass-by-reference)过程中,被调函数的形式参数虽然也作为局部变量在堆栈中开辟了内存空间,但是这时存放的是由主调函数放进来的实参变量的地址。被调函数对形参的任何操作都被处理成间接寻址,即通过堆栈中存放的地址访问主调函数中的实参变量。正因为如此,被调函数对形参做的任何操作都影响了主调函数中的实参变量。

在python中实际又是怎么样的呢?

先看一个简单的例子:

from ctypes import *

import os.path

import sys

def test(c):

print "test before "

print id(c)

c+=2

print "test after +"

print id(c)

return c

def printIt(t):

for i in range(len(t)):

print t[i]

if __name__=="__main__":

a=2

print "main before invoke test"

print id(a)

n=test(a)

print "main afterf invoke test"

print a

print id(a)

运行后结果如下:

>>>

main before invoke test

39601564

test before

39601564

test after +

39601540

main afterf invoke test

2

39601564

id函数可以获得对象的内存地址.很明显从上面例子可以看出,将a变量作为参数传递给了test函数,传递了a的一个引用,把a的地址传递过去了,所以在函数内获取的变量C的地址跟变量a的地址是一样的,但是在函数内,对C进行赋值运算,C的值从2变成了4,实际上2和4所占的内存空间都还是存在的,赋值运算后,C指向4所在的内存。而a仍然指向2所在的内存,所以后面打印a,其值还是2.

如果还不能理解,先看下面例子

>>> a=1

>>> b=1

>>> id(a)

40650152

>>> id(b)

40650152

>>> a=2

>>> id(a)

40650140

a和b都是int类型的值,值都是1,而且内存地址都是一样的,这已经表明了在python中,可以有多个引用指向同一个内存(画了一个很挫的图,见谅),在给a赋值为2后,再次查看a的内存地址,都已经变化了

而基于最前面的例子,大概可以这样描述:

那python函数传参就是传引用?然后传参的值在被调函数内被修改也不影响主调函数的实参变量的值?再来看个例子。

from ctypes import *

import os.path

import sys

def test(list2):

print "test before "

print id(list2)

list2[1]=30

print "test after +"

print id(list2)

return list2

def printIt(t):

for i in range(len(t)):

print t[i]

if __name__=="__main__":

list1=["loleina",25,'female']

print "main before invoke test"

print id(list1)

list3=test(list1)

print "main afterf invoke test"

print list1

print id(list1)

实际值为:

>>>

main before invoke test

64129944

test before

64129944

test after +

64129944

main afterf invoke test

['loleina', 30, 'female']

64129944

发现一样的传值,而第二个变量居然变化,为啥呢?

实际上是因为python中的序列:列表是一个可变的对象,就基于list1=[1,2] list1[0]=[0]这样前后的查看list1的内存地址,是一样的。

>>> list1=[1,2]

>>> id(list1)

64185208

>>> list1[0]=[0]

>>> list1

[[0], 2]

>>> id(list1)

64185208

结论:python不允许程序员选择采用传值还是传引用。Python参数传递采用的肯定是“传对象引用”的方式。这种方式相当于传值和传引用的一种综合。如果函数收到的是一个可变对象(比如字典或者列表)的引用,就能修改对象的原始值--相当于通过“传引用”来传递对象。如果函数收到的是一个不可变对象(比如数字、字符或者元组)的引用,就不能直接修改原始对象--相当于通过“传值'来传递对象。

再附:https://www.jb51.net/article/127667.htm这篇文章的结论不完全对,文章中的不可变对象使用了整数,得出了不可变对象共享这个结论,是错误的,他忽略了小整数池的概念。

python函数传值还是地址_python中给函数传参是传值还是传引用相关推荐

  1. python scatter参数详解_Python中scatter函数参数及用法详解

    最近开始学习Python编程,遇到scatter函数,感觉里面的参数不知道什么意思于是查资料,最后总结如下: 1.scatter函数原型 2.其中散点的形状参数marker如下: 3.其中颜色参数c如 ...

  2. python中int函数的用法浅析_Python中int()函数的用法浅析

    int()是Python的一个内部函数 Python系统帮助里面是这么说的 >>> help(int) Help on class int in module __builtin__ ...

  3. python中int函数是什么作用_python中int函数怎么用

    python中int函数怎么用,字符串,函数,数字,出现在,赋值 python中int函数怎么用 易采站长站,站长之家为您整理了python中int函数怎么用的相关内容. int() 函数用于将一个字 ...

  4. python返回值return用法_Python中return函数返回值代码实例用法

    本篇文章小编给大家分享一下Python中return函数返回值代码实例用法,文章代码介绍的很详细,小编觉得挺不错的,现在分享给大家供大家参考,有需要的小伙伴们可以来看看. return 添加返回值 r ...

  5. python pop函数里有数字_python中pop()函数如何使用

    pop() 函数用于移除列表中的一个元素(默认最后一个元素),并且返回该元素的值. 语法:list.pop(obj=list[-1]) //默认为 index=-1,删除最后一个列表值. //obj ...

  6. python中decode函数在哪个库_python中decode函数的使用方法

    python中decode函数的使用方法 发布时间:2020-12-15 09:22:45 来源:亿速云 阅读:75 作者:小新 这篇文章主要介绍python中decode函数的使用方法,文中介绍的非 ...

  7. python scatter参数详解_Python 中 scatter 函数参数及用法详解

    Python 中 scatter 函数参数及用法详解 Python 中 scatter 函数参数及用法详解 这里有新鲜出炉的 Python 教程, 程序狗速度看过来! Python 编程语言 Pyth ...

  8. python print end报错_python中print()函数的用法和end=不换行详解

    需求:打印五个字符,在一行上 代码: i = 0 while i< 5 : i += 1 print(i,end='') 结果: 1 2 3 4 5那么问题来了,为什么加一个end=" ...

  9. python中的map函数返回一个地址_python中的map函数

    1.对可迭代函数'iterable'中的每一个元素应用'function'方法,将结果作为list返回. 来个例子: >>> def add100(x): ... return x+ ...

最新文章

  1. 快速排序的递归和非递归实现 c语言版本
  2. GZip压缩与解压缩
  3. 我写代码的十八般兵器!
  4. 【以太坊】web3.js的1.0版本和0.2.0版本的安装及区别
  5. Keras【Deep Learning With Python】逻辑回归·softmax多分类与交叉熵
  6. 是否可能存在一种不需要力的相互作用?
  7. 2011.10.17百度面试题
  8. GitLab初次安装后,登录GitLab网页的管理员账号和密码各是什么?
  9. java 什么时候依赖注入_玩框架java依赖注入 – 何时使用单例
  10. 基于java TCP实现网络通信聊天室《建议收藏附完整源码》
  11. nodeJs 接收请求参数和发送请求参数
  12. Android token使用
  13. MagicAjax的用法, 每10秒刷新, 更改等待loading效果
  14. 网页版excel服务器,用excel当数据库,做个简单的网页
  15. 这40个自学网站,一年让你“白捡”十几万,快点收藏
  16. 文件查找工具locatfind
  17. jenkins 管理员邮箱配置
  18. 国家计算机二级和省计算机二级的区别?
  19. C# 控制台程序 打开窗体
  20. 【合辑】数字高程模型科普

热门文章

  1. 《信息安全系统设计基础》实验一 开发环境的熟悉
  2. 性能测试概念点分析与过程讲解(一)
  3. 【piu~】制作一只变形小鸡~
  4. ASP.NET页面跳转
  5. 依赖注入有点_一文读懂Java控制反转(IOC)与依赖注入(DI)
  6. unity3d软阴影和硬阴影的原理_手术无影灯的原理
  7. html5 ocr图片识别,OCR识别控件LEADTOOLS HTML5案例:整页OCR识别
  8. python需要配置环境变量吗_w10版本python怎样设置环境变量
  9. mysql date 默认值_通过Oracle DB了解MySQL
  10. 用户注册PHP,PHP制作用户注册系统,php制作用户注册_PHP教程