函数参数的值传递和引用传递
像我们最熟悉的 C 语言,再写函数参数的同时需要规定函数参数到底是值传递还是引用传递。引用传递导致该参数在函数内的修改出了函数之外也会生效,值传递所有的修改都不会体现到函数外部。
Python 稍微有一点特殊,在定义函数的时候不允许选择参数的传递的方式,传递方式只与参数的数据类型有关。
Python 有 6 中标准的数据类型:Number,String,List,Tuple,Set,Dictionary。不可变数据(3 个):Number(数字)、String(字符串)、Tuple(元组);可变数据(3 个):List(列表)、Dictionary(字典)、Set(集合)。再加上自定义对象,共 7 种数据类型。
其中不可变数据(Number,String,Tuple)为值传递,可变数据(List,Dictionary,Set)和自定义对象为引用传递。
举几个例子就明白了。
Number 值传递
Number 又包含 int、float、bool、complex。
for i in [0,1.2,True,4+3j]:
print("**--------**")
print(i)
def testint(i):
i = 0
testint(i)
print(i)
j = i
j = 0
print(i,j)
输出:
**--------**
0
0
0 0
**--------**
1.2
1.2
1.2 0
**--------**
True
True
True 0
**--------**
(4+3j)
(4+3j)
(4+3j) 0
-
函数内的参数值的改变不会影响到外部
-
把 i 用
=
赋值给 j,i 和 j 互不影响
String 值传递
和 Number 一样:
-
函数内的参数值的改变不会影响到外部
-
把 i 用
=
赋值给 j,i 和 j 互不影响
for i in ["11","abc"]:
print("**--------**")
print(i)
def testint(i):
i = "www"
testint(i)
print(i)
j = i
j = "555"
print(i,j)
**--------**
11
11
11 555
**--------**
abc
abc
abc 555
Tuple 值传递
用的很少,不举例子喽。
List 引用传递
-
函数内的参数值的改变会影响到外部
-
把 i 用
=
赋值给 j,对 j 进行除新赋值之外的任何操作都会影响到 i -
把 j 赋值成另外的值并不会导致 i 也变成同样的值
l = [1,2,3,4,5,6]
print("**--------**")
print(l)
def testint(l):
l.pop()
testint(l)
print(l)
j = l
j.pop()
print(l,j)
j = ["555","666"]
print(l,j)
Dictionary 引用传递
-
函数内的参数值的改变会影响到外部
-
把 i 用
=
赋值给 j,对 j 进行除新赋值之外的任何操作都会影响到 i -
把 j 赋值成另外的值并不会导致 i 也变成同样的值
l = dict()
l[1] = 1
l[2] = 2
print("**--------**")
print(l)
def testint(l):
l.pop(1)
testint(l)
print(l)
j = l
j.pop(2)
print(l,j)
j = ["555","666"]
print(l,j)
Set 引用传递
-
函数内的参数值的改变会影响到外部
-
把 i 用
=
赋值给 j,对 j 进行除新赋值之外的任何操作都会影响到 i -
把 j 赋值成另外的值并不会导致 i 也变成同样的值
l = set()
l.add(1)
l.add(2)
print("**--------**")
print(l)
def testint(l):
l.remove(1)
testint(l)
print(l)
j = l
j.remove(2)
print(l,j)
j = ["555","666"]
print(l,j)
自定义对象 引用传递
将自定义对象或将自定义对象封装在 List/Tuple 种作为参数:
-
函数内的参数值的改变会影响到外部
-
把 i 用
=
赋值给 j,对 j 进行除新赋值之外的任何操作都会影响到 i -
把 j 赋值成另外的值并不会导致 i 也变成同样的值
class Node:
def __init__(self, val = 0, neighbors = []):
self.val = val
self.neighbors = neighbors
n1 = Node(1)
n2 = Node(2)
nl = [n1,n2]
print(nl[0].val)
def t22(nodeList):
nodeList[0].val = 0
t22(nl)
print(nl[0].val)
def t222(node):
node.val = 0
print(n2.val)
t222(n2)
print(n2.val)
-
tips
当自定义类的属性有引用传递对象时,需要将该引用传递对象 copy 一下再传入自定义对象。
class Node:
def __init__(self, val = 0, neighbors = []):
self.val = val
self.neighbors = neighbors
l = [1,2,3,4]
n1 = Node(1,l)
n2 = Node(2,l)
nl = (n1,n2)
print(nl[0].neighbors,nl[1].neighbors,l)
def t22(nodeList):
nodeList[0].neighbors.pop()
t22(nl)
print(nl[0].neighbors,nl[1].neighbors,l)
print(l)
print("---------")
n1 = Node(1,l.copy())
n2 = Node(2,l.copy())
nl = (n1,n2)
print(nl[0].neighbors,nl[1].neighbors,l)
def t22(nodeList):
nodeList[0].neighbors.pop()
t22(nl)
print(nl[0].neighbors,nl[1].neighbors,l)
print(l)
输出:
[1, 2, 3, 4] [1, 2, 3, 4] [1, 2, 3, 4]
[1, 2, 3] [1, 2, 3] [1, 2, 3]
[1, 2, 3]
---------
[1, 2, 3] [1, 2, 3] [1, 2, 3]
[1, 2] [1, 2, 3] [1, 2, 3]
[1, 2, 3]
网友评论