关于copy与deepcopy引发的思考学习

#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))

猜你喜欢

转载自www.cnblogs.com/FanLiu/p/10176165.html