传参一直是语言中有点纠结的东西。一提到这个,总会有人说,需要区分传值,传递引用,还有传递指针什么的。而且,貌似不同的语言对此也有不同的实现。 我自己也对这个有点搞混了,所以需要实验一下。
我常用的几个语言是,c++,go语言,python这几种。三个语言中,只有c++有引用,而python是没有指针的。参数传递主要就两类,传值和传递引用。
本文只写python和go语言,c++太复杂了,需要专门研究。
试验的主要分为几种类型,分别为:
单一的变量类型,比如int,float这种基本类型。实验中使用int。
复杂点的变量类型,比如数组,string,有的自带map等。试验中使用数组。
复合类型研究,比如class,struct。
貌似python根本就没有指针,引用的概念。所以,方便不少。
但是,这也会带来别的问题,因为问题还是存在,传递参数到函数中,函数内对参数的改变,会不会影响到外面的。
代码:
<code>01</code>
<code>#coding=utf-8</code>
<code>02</code>
<code>03</code>
<code>def</code> <code>play(x):</code>
<code>04</code>
<code> </code><code>x</code><code>+</code><code>=</code><code>1</code>
<code>05</code>
<code> </code><code>print</code> <code>"函数内:"</code><code>,x</code>
<code>06</code>
<code>07</code>
<code>x</code><code>=</code><code>1</code>
<code>08</code>
<code>print</code> <code>"初始状态:"</code><code>,x</code>
<code>09</code>
<code>play(x)</code>
<code>10</code>
<code>print</code> <code>"执行play函数后:"</code><code>,x</code>
输出:
<code>1</code>
<code>初始状态: 1</code>
<code>2</code>
<code>函数内: 2</code>
<code>3</code>
<code>执行play函数后: 1</code>
基础变量的传参是复制传参,也就是传值。函数内对变量的操作不会影响外部。
<code> </code><code>x[</code><code>0</code><code>]</code><code>+</code><code>=</code><code>1</code>
<code> </code><code>x[</code><code>1</code><code>]</code><code>+</code><code>=</code><code>3</code>
<code>x</code><code>=</code><code>[</code><code>1</code><code>,</code><code>1</code><code>,</code><code>1</code><code>,</code><code>1</code><code>]</code>
<code>初始状态: [1, 1, 1, 1]</code>
<code>函数内: [2, 4, 1, 1]</code>
<code>执行play函数后: [2, 4, 1, 1]</code>
函数内的改变影响了外部。所以这是<b>传递类的引用</b>。不单单是数组,python的dict等类型都是引用传参(它们其实都是类)。所以需要注意。
<code>class</code> <code>mytest:</code>
<code> </code><code>a</code><code>=</code><code>1</code>
<code> </code><code>b</code><code>=</code><code>1</code>
<code> </code><code>def</code> <code>__repr__(</code><code>self</code><code>):</code>
<code> </code><code>return</code> <code>"a="</code><code>+</code><code>str</code><code>(</code><code>self</code><code>.a)</code><code>+</code><code>",b="</code><code>+</code><code>str</code><code>(</code><code>self</code><code>.b)</code>
<code> </code><code>x.a</code><code>+</code><code>=</code><code>1</code>
<code>11</code>
<code> </code><code>x.b</code><code>+</code><code>=</code><code>3</code>
<code>12</code>
<code>13</code>
<code>14</code>
<code>x</code><code>=</code><code>mytest()</code>
<code>15</code>
<code>16</code>
<code>17</code>
<code>18</code>
<code>初始状态: a=1,b=1</code>
<code>函数内: a=2,b=4</code>
<code>执行play函数后: a=2,b=4</code>
这里,对象被传递到函数中,函数内对实例的操作影响到了外面。所以,这是传递对象的引用。
<code>package main</code>
<code>import </code><code>"fmt"</code>
<code>func add(x </code><code>int</code><code>) {</code>
<code> </code><code>x++</code>
<code> </code><code>fmt.println(</code><code>"函数内的x:"</code><code>,x)</code>
<code>}</code>
<code>func main() {</code>
<code> </code><code>x:=1</code>
<code> </code><code>fmt.println(</code><code>"初始的x:"</code><code>,x)</code>
<code> </code><code>add(x)</code>
<code> </code><code>fmt.println(</code><code>"函数执行后的x: "</code><code>,x)</code>
<code>初始的x: 1</code>
<code>函数内的x: 2</code>
<code>函数执行后的x: 1</code>
看的出来,这是传值,函数内对x的操作并没有影响到外部的x。很明显,调用add函数时,函数copy了一份x。这和python的一样。
<code>func add(ptr *</code><code>int</code><code>) {</code>
<code> </code><code>fmt.println(</code><code>"------函数内------"</code><code>)</code>
<code> </code><code>*ptr++</code>
<code> </code><code>fmt.println(</code><code>"ptr指向的值:"</code><code>,*ptr)</code>
<code> </code><code>fmt.println(</code><code>"ptr指向的地址:"</code><code>,ptr)</code>
<code> </code><code>var ptr *</code><code>int</code><code>=&x</code>
<code> </code><code>fmt.println(</code><code>"ptr指针指向的值:"</code><code>,*ptr)</code>
<code> </code><code>fmt.println(</code><code>"ptr指向的地址:"</code><code>,ptr)</code>
<code> </code><code>add(ptr)</code>
<code> </code><code>fmt.println(</code><code>"------函数执行后-----------"</code><code>)</code>
<code>19</code>
<code> </code><code>fmt.println(</code><code>"ptr指针的值:"</code><code>,*ptr)</code>
<code>20</code>
修改了原来的代码,在主函数声明了一个ptr指针,指向x。然后把指针传递进add函数。
<code>ptr指针指向的值: 1</code>
<code>ptr指向的地址: 0xc208000150</code>
<code>4</code>
<code>------函数内------</code>
<code>5</code>
<code>ptr指向的值: 2</code>
<code>6</code>
<code>7</code>
<code>------函数执行后-----------</code>
<code>8</code>
<code>函数执行后的x: 2</code>
<code>9</code>
<code>ptr指针的值: 2</code>
执行后,外面的x也变成了2.
可以看出,add函数的修改,影响了外部的x。这也是传值,但是,传递的值是一个地址。
<code>func add(array []</code><code>int</code><code>) {</code>
<code> </code><code>array[0]+=1</code>
<code> </code><code>array[1]+=2</code>
<code> </code><code>fmt.println(</code><code>"函数内的数组:"</code><code>,array)</code>
<code> </code><code>array:=[]</code><code>int</code><code>{1,1,1,1}</code>
<code> </code><code>fmt.println(</code><code>"-------初始状态------"</code><code>)</code>
<code> </code><code>fmt.println(</code><code>"初始的数组:"</code><code>,array)</code>
<code> </code><code>add(array)</code>
<code> </code><code>fmt.println(</code><code>"函数执行后的数组:"</code><code>,array)</code>
<code>-------初始状态------</code>
<code>初始的数组: [1 1 1 1]</code>
<code>函数内的数组: [2 3 1 1]</code>
<code>函数执行后的数组: [2 3 1 1]</code>
传递数组和传递指针有着类似的效果,在函数内改变了数组内的值,外面的数组值也改了。这个和c类语言类似。
<code>import </code><code>"strconv"</code>
<code>type test </code><code>struct</code><code>{</code>
<code> </code><code>a </code><code>int</code>
<code> </code><code>b </code><code>int</code>
<code>func (</code><code>this</code> <code>*test)str()string{</code>
<code> </code><code>var tmp string</code>
<code> </code><code>tmp=</code><code>"a:"</code><code>+strconv.itoa(</code><code>this</code><code>.a)+</code><code>" b:"</code><code>+strconv.itoa(</code><code>this</code><code>.b)</code>
<code> </code><code>return</code> <code>tmp</code>
<code>func add(test test){</code>
<code> </code><code>test.a+=1</code>
<code> </code><code>test.b+=2</code>
<code> </code><code>fmt.println(</code><code>"函数中的struct:"</code><code>,test.str())</code>
<code>21</code>
<code> </code><code>test:=test{1,10}</code>
<code>22</code>
<code>23</code>
<code> </code><code>fmt.println(</code><code>"初始的struct:"</code><code>,test.str())</code>
<code>24</code>
<code>25</code>
<code> </code><code>add(test)</code>
<code>26</code>
<code>27</code>
<code> </code><code>fmt.println(</code><code>"函数执行后的struct:"</code><code>,test.str())</code>
<code>28</code>
<code>初始的struct: a:1 b:10</code>
<code>函数中的struct: a:2 b:12</code>
<code>函数执行后的struct: a:1 b:10</code>
被作为参数传入给函数的结构体test,在add函数里对2个值做了加1和加2操作,但是没有影响到外部的变量。这是传值。
从上面的实验来看,无论是python还是go,它们的基础类型在传参时都是复制传参(传值)。对于数组,二者也是一样,类似传递指针,属于传递引用。
但是对于对象,python参数传递类似于指针传递(传对象引用),go语言则是类似于c类语言,属于复制传参。
语言
python
go语言
基础变量传参
传值
数组
传递引用
对象
传递引用(arry,dict属于对象)