他山之石,calling by share——python中既不是传址也不是传值
无论对不变类型变量、可变对象赋值
不可变类型例子1a = 1
b = a
a = 3
print(a,b)
# 3 1可变类型例子2L1 = [1,2,3]
L2 = L1
L1 = 13
print(L1,L2)
# 13 [1, 2, 3]
L1 = ['a','b','c']
print(L1,L2)
# ['a', 'b', 'c'] [1, 2, 3]
L1 = [1,2,3]
L2 = L1
L1[1] = 13
print(L1,L2)
# [1, 13, 3] [1, 13, 3]
L1 = ['a','b','c']
print(L1,L2)
# ['a', 'b', 'c'] [1, 13, 3]
为什么说是调用方法修改属性呢?因为运算符重载中告诉我们,其实"[]"索引其实是自动调用了__getitem__方法(P713)。
记住以上两条,那么即可自如地应对python中参数传递的问题:
代码1:def testImmutable(arg):
arg = 2
print(arg)
a = 1
testImmutable(a)
# 2
print(a)
# 1这个用"对变量赋新值都会断开对原值的引用,而成为新值的引用"解释即可,所以这样的函数无法修改不可变对象。当然,可变对象也是不可以修改代码2:def testMutable(arg):
arg = ['a','b','c']
print(arg)
L = [1,2,3]
testMutable(L)
# ['a', 'b', 'c']
print(L)
# [1, 2, 3](这一点可以跟后面补充内容部分的JS的例子做对比)但是我们可以用方法修改可变对象的属性代码3:def testAttr(args):
args.append(1.3)
a = [1.1,1.2]
print(a)
# [1.1, 1.2]
testAttr(a)
print(a)
# [1.1, 1.2, 1.3]******************************♣******************************P530提到了一个陷阱也就是说我如果想要让形参默认为一个空列表,如果写成这样是有问题的:def saver(x=[]): # Saves away a list object
x.append(1) # Changes same object each time!
print(x)
saver([2]) # Default not used
# [2, 1]
saver() # Default used
# [1]
saver() # Grows on each call!
# [1, 1]
saver()
# [1, 1, 1]这是因为,这个空列表对象只是在def语句执行时被创建的,不会每次函数调用时都得到一个新的列表,所以每次新的元素加入后,列表会在原来的基础上变大,因为这个空列表在每次函数调用的时候都没有被重置正确写法如下:def saver(x=None):
if x is None: # No argument passed?
x = [] # Run code to make a new list each time
x.append(1) # Changes new list object
print(x)
saver([2])
# [2, 1]
saver() # Doesn't grow here
# [1]
saver()
# [1]
如下代码也会报错x = 11
def selector():
print(X)
X = 88
selector()
引用是C++中的概念,其操作符是: & ,这跟C中是取地址操作符一样,
但是意义不一样,C中没有引用的。 (切记 !)
传值,
是把实参的值赋值给行参
那么对行参的修改,不会影响实参的值
传地址
是传值的一种特殊方式,只是他传递的是地址,不是普通的如int
那么传地址以后,实参和行参都指向同一个对象
传引用
真正的以地址的方式传递参数
传递以后,行参和实参都是同一个对象,只是他们名字不同而已
✿例如有人名叫王小毛,他的绰号是“三毛”。说“三毛”怎么怎么的,其实就是对王小毛说三道四。
int num = 10;String str = "hello"; //String是一个引用类型
num = 20;str = "java";‘
void foo(int value) {value = 100;}foo(num); // num 没有被改变
这很容易理解,因为我们传递的是值的副本
void foo(String text) {text = "windows";}foo(str); // str 也没有被改变
str存着地址0x11
StringBuilder sb = new StringBuilder("iphone");void foo(StringBuilder builder) {builder.append("4");}foo(sb); // sb 被改变了,变成了"iphone4"。
sb是一个StringBuilder对象,他的地址0x21被传递给builder
StringBuilder sb = new StringBuilder("iphone");void foo(StringBuilder builder) {builder = new StringBuilder("ipad");}foo(sb); // sb 没有被改变,还是 "iphone"。
public class TestMain {public static void main(String[] args) {List<Integer> list = new ArrayList<Integer>();for (int i = 0; i < 10; i++) {list.add(i);}add(list);for (Integer j : list) {System.err.print(j+",");;}System.err.println("");System.err.println("*********************");String a="A";append(a);System.err.println(a);int num = 5;addNum(num);System.err.println(num);}static void add(List<Integer> list){list.add(100);}static void append(String str){str+="is a";}static void addNum(int a){a=a+10;}}
打印出来的结果是:
var obj = {x : 1};function foo(o) {o = 100;}foo(obj);console.log(obj.x); // 仍然是1, obj并未被修改为100.
如果是按引用传递,修改形参o的值,应该影响到实参才对。但这里修改o的值并未影响obj。 因此JS中的对象并不是按引用传递。那么究竟对象的值在JS中如何传递的呢?
他山之石,calling by share——python中既不是传址也不是传值的更多相关文章
- python中导入一个需要传参的模块
最近跑实验,遇到了一个问题:由于实验数据集比较多,每次跑完一个数据集就需要手动更改文件路径,再将文件传到服务器,再运行实验,这样的话效率很低,必须要专门看着这个实验,啥时候跑完就手动修改运行下一个实验 ...
- python 中的metaclass和baseclasses
提前说明: class object 指VM中的class 对象,因为python一切对象,class在VM也是一个对象,需要区分class对象和 class实例对象. class instance ...
- Python中的内置函数
2.1 Built-in Functions The Python interpreter has a number of functions built into it that are alway ...
- Python中super()的用法
参考链接:https://www.cnblogs.com/shengulong/p/7892266.html super 是用来解决多重继承问题的,直接用类名调用父类方法在使用单继承的时候没问题,但是 ...
- python中的__enter__ __exit__
我们前面文章介绍了迭代器和可迭代对象,这次介绍python的上下文管理.在python中实现了__enter__和__exit__方法,即支持上下文管理器协议.上下文管理器就是支持上下文管理器协议的对 ...
- python中GIL和线程与进程
线程与全局解释器锁(GIL) 一.线程概论 1.何为线程 每个进程有一个地址空间,而且默认就有一个控制线程.如果把一个进程比喻为一个车间的工作过程那么线程就是车间里的一个一个流水线. 进程只是用来把资 ...
- OpenCV-Python(1)在Python中使用OpenCV进行人脸检测
OpenCV是如今最流行的计算机视觉库,而我们今天就是要学习如何安装使用OpenCV,以及如何去访问我们的摄像头.然后我们一起来看看写一个人脸检测程序是如何地简单,简单到只需要几行代码. 在开始之前, ...
- 如何将xml转为python中的字典
如何将xml转为python中的字典 import cElementTree as ElementTree class XmlListConfig(list): def __init__(self, ...
- Python 中的属性访问与描述符
在Python中,对于一个对象的属性访问,我们一般采用的是点(.)属性运算符进行操作.例如,有一个类实例对象foo,它有一个name属性,那便可以使用foo.name对此属性进行访问.一般而言,点(. ...
随机推荐
- 【Solution】MySQL 5.8 this is incompatible with sql_mode=only_full_group_by
[42000][1055] Expression #1 of SELECT list is not in GROUP BY clause and contains nonaggregated colu ...
- 20175211 2018-2019-2 《Java程序设计》第五周学习总结
目录 教材学习内容总结 第六章 接口与实现 教材学习中的问题和解决过程 代码调试中的问题和解决过程 代码托管 上周考试错题总结 学习进度条 参考资料 教材学习内容总结 第六章 接口与实现 6.1 接口 ...
- python3.6安装docx模块
1.下载 python_docx-0.8.6-py2.py3-none-any.whl 地址: http://www.lfd.uci.edu/~gohlke/pythonlibs/2.在这个网页的最下 ...
- windows 下面make的使用示例
---恢复内容开始--- 前面已经安装了windows下面的编译器g++和mingw32-make,下面就make做个示例说明 1.文档结构 |--src |--comm ...
- go 语言环境搭建(Ubuntu + Sublime Text3 + GoSublime + gocode)
1. 首先安装go http://code.google.com/p/golang-china/wiki/Install 或者http://golang.org/doc/install这里有详细介绍. ...
- 取模性质,快速幂,快速乘,gcd和最小公倍数
一.取模运算 取模(取余)运算法则: 1. (a+b)%p=(a%p+b%p)%p; 2.(a-b)%p=(a%p-b%p)%p; 3.(a*b)%p=(a%p * b%p)%p; 4.(a^b)%p ...
- jquery判断字符长度 数字英文算1字符 汉字算2字符
<input type="text" maxlength="25" oninput="textlength(this)"> &l ...
- python中pip升级
第一步: 首先安装python,在百度中搜索python,进入python官网,点击downliad, 下载到本地: 下载好后进行安装,与一般软件安装过程一样.安装过程中要注意勾线Add python ...
- 设置VS2017背景图片
设置方法很简单:安装扩展ClaudiaIDE 1.在这里下载扩展,https://visualstudiogallery.msdn.microsoft.com/9ba50f8d-f30c-4e33-a ...
- sql多行多列重复
在sql的查询中我们会遇到查询的结果比如这样的: 查询这张表的sql语句: select r.ROLE_NAME,u.USERID,u.USERNAME,u.TrueName from BASE_ ...