python的参数传递

值传递和引用传递的解释

值传递,通常就是拷贝参数的值,然后传递给函数里的新变量。这样,原变量和新变量之间互相独立,互不影响。
引用传递,通常是指把参数的引用传给新的变量,这样,原变量和新变量就会指向同一块内存地址。如果改变了其中任何一个变量的值,那么另外一个变量也会相应地随之改变。

知道了这两种传递的解释后,再来了解一下python变量的初始化
1、对于整型(int)、字符串(string)等等,是不可变的。所以,a = a + 1,并不是让 a 的值增加 1,而是表示重新创建了一个新的值为 2 的对象,然后让a指向它。

a = 1
b = a
a = a + 1
print(a)
print(b)

这儿只是表明,a或者b都指向了同一个对象1,或者说,对象1有两个名字,分别是a和b。
指向同一个对象,但是并不是表面这两个变量就绑定在一起了,你修改其中一个变量a,那么a变了,b还是原来的那个变量。
2、对于可变的类型列表等

l1 = [1, 2, 3]
l2 = l1
l1.append(4)
print(l1)
print(l2)

列表是可变的,所以 l1.append(4) 不会创建新的列表,只是在原列表的末尾插入了元素 4,变成 [1, 2, 3, 4]。由于 l1 和 l2 同时指向这个列表,所以列表的变化会同时反映在 l1 和 l2 这两个变量上,那么,l1 和 l2 的值就同时变为了 [1, 2, 3, 4]。
此外,python变量可以删除,对象不可以

l = [1, 2, 3]
del l

但是删除l后,只是l这个变量没了,但是[1,2,3]这个对象仍然存在,Python 程序运行时,其自带的垃圾回收系统会跟踪每个对象的引用。如果 [1, 2, 3] 除了 l 外,还在其他地方被引用,那就不会被回收,反之则会被回收。

综上:

  • 变量的赋值,只是表示让变量指向了某个对象,并不表示拷贝对象给变量;而一个对象,可以被多个变量所指向。
  • 可变对象(列表,字典,集合等等)的改变,会影响所有指向该对象的变量。
  • 对于不可变对象(字符串,整型,元祖等等),所有指向该对象的变量的值总是一样的,也不会改变。但是通过某些操作(+= 等等)更新不可变对象的值时,会返回一个新的对象。
  • 变量可以被删除,但是对象无法被删除。

函数的参数传递

Python 的参数传递是赋值传递 (pass by assignment),或者叫作对象的引用传递(pass by object reference)。Python 里所有的数据类型都是对象,所以参数传递时,只是让新变量与原变量指向相同的对象而已,并不存在值传递或是引用传递一说。
1、对于不可变的变量传递

def my_func1(b):
	b = 2
 
a = 1
my_func1(a)
print(a)
#1

这里,a和b都指向了1这个对象,但是当指向到b=2的时候,b就指向了2这个新对象,但是a还是指向1这个对象,a的值所以还是1

def my_func1(b):
	b = 2
	return b
 
a = 1
my_func1(a)
print(a)
#2

但是让函数返回新的变量的时候,这个时候就会把新的对象2交给a,那么a就指向了一个新的对象2。从而产生了数据发送改变。
2、对于不可变对象,就会影响所有指向当前对象的变量的值

def my_func3(l2):
	l2.append(4)
 
l1 = [1, 2, 3]
my_func3(l1)
print(l1)
#[1, 2, 3, 4]

列表是一个可变对象,当进行append操作的时候,对其末尾加入新元素 4 时,变量 l1 和 l2 的值也都随之改变了。

def my_func4(l2):
	l2 = l2 + [4]
 
l1 = [1, 2, 3]
my_func4(l1)
print(l1)
#[1, 2, 3]

这里 l2 = l2 + [4],表示创建了一个“末尾加入元素 4“的新列表,并让 l2 指向这个新的对象。这个过程与 l1 无关,因此 l1 的值不变。

a、那么对于以下这个问题,是否是同一个对象。

l1 = [1, 2, 3]
l2 = [1, 2, 3]
l3 = l2

列表是可变对象,每创建一个列表都会重新分配内存,所以 l1 、 l2 并不是同一个对象,但是 l3 = l2 ,表明 l3 指向 l2 的对象。

b、下面这个b的值

def func(d):
    d['a'] = 10
	d['b'] = 20
	d = {'a': 1, 'b': 2}

d = {}
func(d)
print(d)
# {'b': 20, 'a': 10}

d[‘a’]相当于append操作,只是在原始字典进行操作,不会创建一个新的对象,所以局部变量和全局变量d都变成了{‘b’: 20, ‘a’: 10},但是d = {‘a’: 1, ‘b’: 2}会创建一个新的对象,并且将新的值只是给了局部变量。

    def func(d):
        d['a'] = 10
        d['b'] = 20
        d = {'a': 1, 'b': 2}
        return d

    d = {}
    func(d)
    print(d)
    #{'b': 20, 'a': 10}
    print(func(d))
    #{'b': 2, 'a': 1}

总结:
如果对象是可变的,当其改变时,所有指向这个对象的变量都会改变。
如果对象不可变,简单的赋值只能改变其中一个变量的值,其余变量则不受影响。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值