python和java,值传递和引用传递

不得不提

引用是C++的概念,将它运用在其他语言上面已经是不太必要。如果还要仔细扣概念,那真容易懵逼,所以,请把关注点放在效果上。

引出问题

不久前有个面试官在笔试题中问我:

python的参数传递是值传递还是引用传递?

我当时的回答是:

引用传递,python中没有明确的值类型和引用类型的概念,一般可以将不可变类型类比为值类型,可变类型类比为引用类型。

当时看到这个题,是有一点无从下手的,因为我知道如果将不可变类型的变量如 int、str传入函数,函数里面修改这些变量的值,是不会影响到函数外部变量的值。如果传入可变类型变量如 list ,则函数里面的操作会改变原来变量的值。

这难道不是值传递和引用传递都有吗?如果要选一个那么我选引用传递。于是上面的答案应运而生,不太放心就继续写了一段话想表现一下自己的知识水平。

最终,他否了我,这个回答是否合他心意(记住这个词)也不得而知。问他也不再理我,很不理解为什么。

答案究竟是什么

首先,不讨论所谓堆和栈的问题。python中很少提到这个概念,有时不要试图去用其他语言的那套思想理解python。

无论是可变类型变量还是不可变类型变量,传入函数的都是引用。区别在于:

  1. 当参数是不可变类型时,函数体内修改它的值时,会开辟一个新的空间,将局部变量指向这个空间。原来的变量不会被修改,不会发生共享内存的问题。
  2. 当参数是可变类型时,函数体内修改它的值就不会开辟新空间,修改操作会直接作用在原来的变量上。
a = "我爱你"
def f1(b):
    print(id(b))

print(id(a))
f1(a)
# 结果 a和b id值相同
a = "我爱你"
def f1(b):
    b = "我爱你"
    print(id(b))

print(id(a))
f1(a)
# 结果 a和b id值不同

以上说法也有其他博客总结为

python不允许程序员选择采用传值还是传引用。python参数传递采用的肯定是“传对象引用”的方式。这种方式相当于传值和传引用的一种综合。如果函数收到的是一个不可变对象(数字、字符或元组)的引用,就不能直接修改原始对象–相当于通过‘值传递’来传递对象。如果函数收到的是一个可变对象(字典、列表)的引用,就能修改对象的原始值–相当于‘传引用’来传递对象。

我觉得第一句话很好。python无论怎么传参数,就一种,把变量名给函数就完了。不像C++, 变量,&变量,*变量。
所以还是那句,不要用别的语言那套思想理解python,有时候越想越蒙。

所以,答案不唯一,说法不唯一。不知道是否合他心意。

总结

如果非要用其他语言的传值还是传引用的概念或效果来类比python的参数传递。那么就是不可变类型变量作为参数时传值,可变类型变量作为参数时传引用。

一个易错点

def bad_append(new_item, a_list=[]):
 
    a_list.append(new_item)
 
    return a_list

这段代码是初学者最容易犯的错误,用可变(mutable)对象作为参数的默认值。函数定义好之后,默认参数 a_list 就会指向(绑定)到一个空列表对象,每次调用函数时,都是对同一个对象进行 append 操作。因此这样写就会有潜在的bug,同样的调用方式返回了不一样的结果。
而正确的方式是,把参数默认值指定为None

Java中没有引用传递

有很多小伙伴都有如下想法:Java中的对象有在堆中创建的,而栈中的变量只是一个地址引用,所以当调用方法时传递过去的就是实际就是堆中对象的地址引用。所以他们认为,在Java中,对象就是引用传递。其实不是的,请仔细阅读引用传递的概念,它是指传递过去的是这个变量的引用而不是对象的引用,也就是传递过去的这个实参就是栈中这个变量的引用。但是实际是在调用方法时,它传递的就是这个变量的一个一副本,一个复制值,但是这个复制值就是所指向的对象地址还是那个,所以修改这个对象时,其实修改的是堆中对象的值

这句话将传引用和传地址的概念进行区分了。

最后一提

知道效果就好。 非要回答这个问题就按照大家一贯的说法吧。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值