前言
现在有很多的语言,我所学习过的有python、java、C/C++、JavaScript等,即使已经学习了不少的语言,有时候也会被函数的传参方式给搞晕了,本文主要说明一下python的传参方式,并简单说明与C/C++的不同之处。
Python传参方式说明
def test(num,_str,_list):
num = 10
_str = "aaa"
_list = [1,2,3]
if __name__ == '__main__':
num = 100
_str = "aaabbb"
_list = [1, 2, 3,4]
test(num,_str,_list)
print(num)
print(_str)
print(_list)
结果:
100
aaabbb
[1, 2, 3, 4]
是的这样传递参数,函数中去改变,我连变量名都没有换,但是却都不能改变他们的值。下面我再对代码做一个变化:
def test(num,_str,_list):
num = 10
#在这里加上+=
_str += "aaa"
_list += [1,2,3]
if __name__ == '__main__':
num = 100
_str = "aaabbb"
_list = [1, 2, 3,4]
test(num,_str,_list)
print(num)
print(_str)
print(_list)
结果:
100
aaabbb
[1, 2, 3, 4, 1, 2, 3]
这是为什么呢?
如果再说说C++或者C语言的传递方式,可能会混乱,其实只要弄清除本质,那么就真的很简单。下面是重点,敲黑板!
在Python,Java这样的纯面向对象语言,它们的思想就是万物皆是对象,所以呢,请记住一句话,它们的函数传参方式叫做对象传递,没错就是对象传递,好像是我造出来的,不过真的很贴切。
python中的变量名其实只是一个标签,比如代码中的num、_str都标签,这个时候只是说把num标签贴在数字100上面,然后把100这个对象传递给函数,虽然我用了同名num但是其实,现在函数的这个num只是一个新的标签,跟原来的num是两个不同的标签,然后这个标签现在也指向100,但是后面函数中,把这个标签贴在了10上面,于是乎,这个新的标签就代表10,而老标签也依然还是100。同样的道理可以再去分析一下_str,+=这个操作等价于,把_str这个标签贴在了新的字符串上,但是老的标签的那个对象还是没变的。而_list为什么变了,因为list的+=会改变原来的对象,所以,老标签贴的对象没变,但是内容被改变了。
其实,再来理解一下,数值,字符串字面值,元祖,这样的对象是不可能被改变的,而列表、字典或者自己用类创建的对象,这样的是可以被改变的,也就是说,标签贴的对象还是不会变的,只是因为对象能变的话,那就变,否则,对象内容没变,也就没变了,我也知道确实有点绕,但是仔细理解就一句话:我传了一个对象给你,你用一个新标签贴在上面,你要是改变对象的内容,那么对象必须要可变,否则你就把标签撕下来,贴在新的对象上而已,原来的标签总是贴在原来的对象上,你没法改变!
Java
Java中的函数传参方式也是这样的,其他没有指针的面向对象的语言也基本是这样的,只要你真的理解这个了,保证不会再为这种东西而懵逼了!想想都刺激,有的写了很久代码的人可能还会为这个困惑,甚至有时候直接犯错,我一点也不夸张的。只要你掌握了!
C/C++
C/C++有三种函数传参方式:
- 值传递:只是把变量的内容传递过去,函数内的操作无法改变原变量的值。
- 指针传递:这个就比较厉害了,就是把变量所指向的内存地址传递过去,这时候,就可以通过指针去更改,这块内存的值,那么当然也就改变了原变量的值,但是要注意,只读区的值,虽然也可以通过这种方式修改,但是千万不要这么做,上帝给了你权限,你也不可以滥用。
- 引用传递:这种方式只有C++有,就是把变量的引用传递给你,你可以任意改变,其实引用传递的本质是指针传递,还是那句话:上帝给了你权限,你也不可以滥用。
总结:
其实传参方式真的有时候很难理解,但是如果真的把我上述的内容理解透了,这方面就不成问题了!
愿每一个程序员都能被温柔相待