# 函数传值问题

先看一个例子：

```python
# -*- coding: UTF-8 -*-
def chagne_number( b ):
    b = 1000

b = 1
chagne_number(b)
print( b )
```

最后输出的结果为：

```txt
1
```

先看看运行的结果？

想一下为什么打印的结果是 1 ，而不是 1000 ？

其实把问题归根结底就是，为什么通过函数 `chagne_number` 没有更改到 b 的值？

这个问题很多编程语言都会讲到，原理解释也是差不多的。

这里主要是函数参数的传递中，传递的是类型对象，之前也介绍了 Python 中基本的数据类型等。而这些类型对象可以分为可更改类型和不可更改的类型

**在 Python 中，字符串，整形，浮点型，tuple 是不可更改的对象，而 list ， dict 等是可以更改的对象。**

例如：

**不可更改的类型**：变量赋值 `a = 1`，其实就是生成一个整形对象 1 ，然后变量 a 指向 1，当 `a = 1000` 其实就是再生成一个整形对象 1000，然后改变 a 的指向，不再指向整形对象 1 ，而是指向 1000，最后 1 会被丢弃

**可更改的类型**：变量赋值 `a = [1,2,3,4,5,6]` ，就是生成一个对象 list ，list 里面有 6 个元素，而变量 a 指向 list ，`a[2] = 5`则是将 list a 的第三个元素值更改,这里跟上面是不同的，并不是将 a 重新指向，而是直接修改 list 中的元素值。

![指向问题](http://upload-images.jianshu.io/upload_images/2136918-31b1031d75e1cec9?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

这也将影响到函数中参数的传递了：

**不可更改的类型**：类似 c++ 的值传递，如 整数、字符串、元组。如fun（a），传递的只是 a 的值，没有影响 a 对象本身。比如在 fun（a）内部修改 a 的值，只是修改另一个复制的对象，不会影响 a 本身。

**可更改的类型**：类似 c++ 的引用传递，如 列表，字典。如 fun（a），则是将 a 真正的传过去，修改后 fun 外部的 a 也会受影响

因此，在一开始的例子中，`b = 1`,创建了一个整形对象 1 ，变量 b 指向了这个对象，然后通过函数 chagne\_number 时，按传值的方式复制了变量 b ，传递的只是 b 的值，并没有影响到 b 的本身。具体可以看下修改后的实例，通过打印的结果更好的理解。

```python
# -*- coding: UTF-8 -*-
def chagne_number( b ):
    print('函数中一开始 b 的值：{}' .format( b ) )
    b = 1000
    print('函数中 b 赋值后的值：{}' .format( b ) )


b = 1
chagne_number( b )
print( '最后输出 b 的值：{}' .format( b )  )


```

打印的结果：

```txt
函数中一开始 b 的值：1
函数中 b 赋值后的值：1000
最后输出 b 的值：1
```

当然，如果参数中的是可更改的类型，那么调用了这个函数后，原来的值也会被更改，具体实例如下：

```python
# -*- coding: UTF-8 -*-

def chagne_list( b ):
    print('函数中一开始 b 的值：{}' .format( b ) )
    b.append(1000)
    print('函数中 b 赋值后的值：{}' .format( b ) )


b = [1,2,3,4,5]
chagne_list( b )
print( '最后输出 b 的值：{}' .format( b )  )
```

输出的结果：

```txt
函数中一开始 b 的值：[1, 2, 3, 4, 5]
函数中 b 赋值后的值：[1, 2, 3, 4, 5, 1000]
最后输出 b 的值：[1, 2, 3, 4, 5, 1000]
```
