# 12.函数

## 1. 函数的定义

```python
def 函数名（参数列表）:
    函数体
```

Python中的函数以 `def` 关键字定义，后接 **函数名**，**参数列表**在 `()` 中，`:` 之后接**函数体**\
​

#### Tip

**python**中的函数不显示指定返回值类型，根据 **return语句** 的返回值自动判断。 如果没有 **return** 语句，则返回 None\
​

## 2. 参数传递

python 中的一切都是对象，变量中保存的是对象的地址。

因此函数中的参数传递方式就是引用传递(指针传递)。但是需要注意的是 python 中的对象分为 **可变类型** 和 **不可变类型**。

* **不可变类型**：作为参数传递到函数中后，不能修改对象的值，只能够修改参数变量中保存的对象地址. 这样的表现则像是值传递(尽管事实上并不是)

  不可变类型有 numbers，str，tuple，

```python

def change(a):
    print(id(a))   # 指向的是同一个对象
    a=10
    print(id(a))   # 一个新对象
 
a=1
print(id(a))
change(a)

'''
4344209672
4344209672
4344209960
'''

```

* **可变类型** : 可变类型的表现就完全是正常的引用传递

## 3. 参数类型

python中的参数分为：

* 必需参数
* 关键字参数
* 默认参数
* 不定长参数

#### 必需参数

**必需参数**必须是按照声明时的顺序，数量进行传递，否则会出现语法错误

```python
def min(a,b):
    if a > b :
        return b
    else :
        return a

print(min(11)) # 报错，缺少一个参数
```

![](https://pic.existorlive.cn/202112030147517.png)

#### 关键字参数

参数在传递时以**参数名**作为**关键字**，这样参数就不是必须以声明时的顺序传递

```python
print(min(b=11,a=2))    # a,b的顺序可以颠倒
```

#### 默认参数

参数在声明时可以指定默认参数

```python
#可写函数说明
def printinfo( name, age = 35 ):
   "打印任何传入的字符串"
   print ("名字: ", name)
   print ("年龄: ", age)
   return
 
#调用printinfo函数
printinfo( age=50, name="runoob" )
print ("------------------------")
printinfo( name="runoob" )
```

注意一点，同 C++/Swift 一样，默认参数后的参数也必须是默认参数

#### 不定长参数

你可能需要一个函数能处理比当初声明时更多的参数。

```python
def functionname([formal_args,] *var_args_tuple ):
   "函数_文档字符串"
   function_suite
   return [expression]

def functionname([formal_args,] **var_args_dict ):
   "函数_文档字符串"
   function_suite
   return [expression]
```

\[ \*参数名 ], 在函数内使用时是一个元组

\[ \*\*参数名 ] 在函数内使用时是一个字典

```python
# 可写函数说明
def printinfo( arg1, *vartuple ):
   "打印任何传入的参数"
   print ("输出: ")
   print (arg1)
   for var in vartuple:
      print (var)
   return
 
# 调用printinfo 函数
printinfo( 10 )
printinfo( 70, 60, 50 )

# 可写函数说明
def printinfo( arg1, **vardict ):
   "打印任何传入的参数"
   print ("输出: ")
   print (arg1)
   print (vardict)
 
# 调用printinfo 函数
printinfo(1, a=2,b=3)
```

## 4. 匿名函数/lambda表达式

python中使用 **lambda** 关键字创建匿名函数

```python
lambda [arg1 [,arg2,.....argn]]:expression
```

**lambda** 关键字后直接跟 **参数列表** 和 **函数体**，不需要函数名

```python
# 可写函数说明
sum = lambda arg1, arg2: arg1 + arg2
 
# 调用sum函数
print ("相加后的值为 : ", sum( 10, 20 ))
print ("相加后的值为 : ", sum( 20, 20 ))
```

* lambda 只是一个表达式，函数体比 def 简单很多。
* lambda的主体是一个表达式，而不是一个代码块。仅仅能在lambda表达式中封装有限的逻辑进去。
* **lambda 函数拥有自己的命名空间，且不能访问自己参数列表之外或全局命名空间里的参数**。
* 虽然lambda函数看起来只能写一行，却不等同于C或C++的内联函数，后者的目的是调用小函数时不占用栈内存从而增加运行效率。


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://gitbook.existorlive.cn/kai-fa-yu-yan-xue-xi/python/12.-han-shu.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
