#1. 传值与传址的区别
# 传值就是传入一个参数的值,传址就是传入一个参数的地址,也就是内存的地址(相当于指针)。
#他们的区别是如果函数里面对传入的参数重新赋值,函数外的全局变量是否相应改变:用传值传入的参数是不会改变的,用传址传入就会。
1 ''' 2 an是一个list,将其作为实参传入函数a中,a对其第三个元素进行修改。a执行结束后再次打印an,发现里面的元素的确发生变化,这就是传址操作。 3 4 ''' 5 def a(n): 6 n[2] = 100 7 print(n) 8 return None 9 ''' 10 bn代表一个数字,将其传入函数b,并做修改,b执行结束后再次打印bn,没有变化,这是传值操作。 11 ''' 12 def b(n): 13 n += 100 14 print(n) 15 return None 16 17 an = [1,2,3,4,5] 18 bn = 10 19 20 print(an) 21 print(id(an)) 22 a(an) 23 print(an) 24 print(id(an)) 25 print(bn) 26 print(id(bn)) 27 b(bn) 28 print(bn) 29 print(id(bn))
# Python中传值与传址的规律
# Python是不允许程序员选择采用传值还是传址的。Python参数传递采用的是“传对象引用”的方式,实际上,这种方式相当于传值和传址的一种综合。
# 如果函数收到的是一个可变对象(比如字典或者列表)的引用,就能修改对象的原始值——相当于传址。如果函数收到的是一个不可变对象(比如数字、字符或者元组)的引用,就不能直接修改原始对象——相当于传值。
# 所以python的传值和传址是根据传入参数的类型来选择的。
# 传值的参数类型:数字,字符串,元组
# 传址的参数类型:列表,字典
# tuple元组是不可修改的,指的是其元组内容不可改。但是其所指向的内存地址是可变的。 t1 = (1,2,3) t2 = (5,6,7) print(t1) print(id(t1)) print(t2) print(id(t2)) t1 += t2 print(t1) print(id(t1)) print(id(t2)) t2 *= 3 print(t2) print(id(t2))
#为了提高内存利用效率,对于一些简单的对象,如一些数值较小的int对象,python采取重用对象内存的办法。
# 如指向a=100,c=100时,由于100作为简单的int类型且数值小,python不会两次为其分配内存,而是只分配一次,然后将a与c同时指向已分配的对象。
# 但是当a的值发生变化时,会单独为a重新分配一个新的内存。
# 当把a的值赋值给C时为了节省内存只是在内存指向上同时把这一片内存指向了a和c。 a = 100 print(id(a)) c = a print(id(c)) print(a is c) # 当a的值发生变化的时候则才会重新分配一片内存指向给a a += 300 print(a) print(c) print(a is c) print(id(a)) print(id(c))
# 列表的切片也是相当于是一种传址的操作
# 列表的切片也是相当于是一种传址的操作 a = [1,2,3,4,5,6,7,8,9] b = a[:] c = a[0:4:2] print(a) print(b) print(c) print(id(a)) print(id(b)) print(id(c)) print("此处是分割线 " * 5) # 类似这种的操作叫做传址或者是传引用的方式,这种操作方式当进行赋值操作的时候id并未改变只是把地址内的值进行了更改 l = [1,2,3,4,5,6,7,8,9] print(l) l[2] = 100 print(id(l)) print(l) print(id(l))