Python初学者笔记(八):函数参数的值传递和引用传递

函数参数的值传递和引用传递

像我们最熟悉的 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
  1. 函数内的参数值的改变不会影响到外部

  2. 把 i 用 = 赋值给 j,i 和 j 互不影响

String 值传递

和 Number 一样:

  1. 函数内的参数值的改变不会影响到外部

  2. 把 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 引用传递

  1. 函数内的参数值的改变会影响到外部

  2. 把 i 用 = 赋值给 j,对 j 进行除新赋值之外的任何操作都会影响到 i

  3. 把 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 引用传递

  1. 函数内的参数值的改变会影响到外部

  2. 把 i 用 = 赋值给 j,对 j 进行除新赋值之外的任何操作都会影响到 i

  3. 把 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 引用传递

  1. 函数内的参数值的改变会影响到外部

  2. 把 i 用 = 赋值给 j,对 j 进行除新赋值之外的任何操作都会影响到 i

  3. 把 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 种作为参数:

  1. 函数内的参数值的改变会影响到外部

  2. 把 i 用 = 赋值给 j,对 j 进行除新赋值之外的任何操作都会影响到 i

  3. 把 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]

你可能感兴趣的:(Python初学者笔记(八):函数参数的值传递和引用传递)