|
1 | | -# 5.2 【基础】匿名函数 |
| 1 | +# 5.2. 【基础】11个案例讲解函数参数 |
2 | 2 |
|
3 | | -匿名函数(英语:anonymous function)是指一类无需定义标识符(函数名)的函数。通俗来说呢,就是它可以让我们的函数,可以不需要函数名。 |
| 3 | +## 1. 参数分类 |
4 | 4 |
|
5 | | -正常情况下,我们定义一个函数,使用的是 `def` 关键字,而当你学会使用匿名函数后,替代 `def` 的是 `lambda`。 |
| 5 | +函数,在定义的时候,可以有参数的,也可以没有参数。 |
6 | 6 |
|
7 | | -这边使用`def` 和 `lambda` 分别举个例子,你很快就能理解。 |
| 7 | +在 Python 中参数的种类,大概可以分为四种 |
| 8 | + |
| 9 | +1. `必选参数`,也叫`位置参数`,调用函数时一定指定的参数,并且在传参的时候必须按函数定义时的顺序来 |
| 10 | +2. `可选参数`,也叫`默认参数`,调用函数时,可以指定也可以不指定,不指定就默认的参数值来。 |
| 11 | +3. `可变参数`,就是参数个数可变,可以是 0 个或者任意个,但是传参时不能指定参数名,通常使用 `*args` 来表示。 |
| 12 | +4. `关键字参数`,就是参数个数可变,可以是 0 个或者任意个,但是传参时必须指定参数名,通常使用 `**kw` 来表示 |
| 13 | + |
| 14 | +## 2. 十个案例 |
| 15 | + |
| 16 | +**案例一**:在下面这个函数中, a 是位置参数,必须要指定的 |
8 | 17 |
|
9 | 18 | ```python |
10 | | -def mySum(x, y): |
11 | | - return x+y |
12 | | -mySum(2, 3) |
13 | | -# 5 |
| 19 | +>>> def demo_func(a): |
| 20 | +... print(a) |
| 21 | +... |
| 22 | +>>> demo_func(10) |
| 23 | +10 |
| 24 | +>>> demo_func() # 不指定会报错 |
| 25 | +Traceback (most recent call last): |
| 26 | + File "<stdin>", line 1, in <module> |
| 27 | +TypeError: demo_func() missing 1 required positional argument: 'a' |
| 28 | +``` |
| 29 | + |
| 30 | + **案例二**:在下面这个函数中,b 是默认参数,可以指定也可以不指定,不指定的话,默认为10 |
14 | 31 |
|
15 | | -(lambda x, y: x+y)(2, 4) |
16 | | -# 6 |
| 32 | +```python |
| 33 | +>>> def demo_func(b=10): |
| 34 | +... print(b) |
| 35 | +... |
| 36 | +>>> demo_func(20) |
| 37 | +20 |
| 38 | +>>> demo_func() |
| 39 | +10 |
17 | 40 | ``` |
18 | 41 |
|
19 | | -从上面的示例,我们可以看到匿名函数直接运行,省下了很多行的代码,有没有? |
| 42 | +**案例三**:在下面这个函数中, name 和 age 都是位置参数,在调用指定参数时,需要注意顺序 |
20 | 43 |
|
21 | | -接下来,我们的仔细看一下它的用法 |
| 44 | +```python |
| 45 | +>>> def print_profile(name, age): |
| 46 | +... return f"我的名字叫{name},今年{age}岁了" |
| 47 | +... |
| 48 | +>>> print_profile("王炳明", 27) |
| 49 | +'我的名字叫王炳明,今年27岁了' |
| 50 | +``` |
22 | 51 |
|
23 | | -带 if/else |
| 52 | +如果参数太多,你不想太花精力去注意顺序,可以在指定参数时,附上参数名,比如这样: |
24 | 53 |
|
25 | 54 | ```python |
26 | | ->>>( lambda x, y: x if x < y else y )( 1, 2 ) |
27 | | -1 |
| 55 | +>>> print_profile(age=27, name="王炳明") |
| 56 | +'我的名字叫王炳明,今年27岁了' |
28 | 57 | ``` |
29 | 58 |
|
30 | | -嵌套函数 |
| 59 | +**案例四**:在下面这个函数中,`args` 参数和上面的参数名不太一样,在它前面有一个 `*`,这就表明了它是一个可变参数,可以接收任意个数的不指定参数名的参数。 |
31 | 60 |
|
32 | 61 | ```python |
33 | | ->>>( lambda x: ( lambda y: ( lambda z: x + y + z )( 1 ) )( 2 ) )( 3 ) |
34 | | -6 |
| 62 | +>>> def demo_func(*args): |
| 63 | +... print(args) |
| 64 | +... |
| 65 | +>>> |
| 66 | +>>> demo_func(10, 20, 30) |
| 67 | +(10, 20, 30) |
35 | 68 | ``` |
36 | 69 |
|
37 | | -递归函数 |
| 70 | +**案例五**:在下面这个函数中,`kw` 参数和上面的 `*args` 还多了一个 `*` ,总共两个 `**` ,这个意思是 `kw` 是一个可变关键字参数,可以接收任意个数的带参数名的参数。 |
38 | 71 |
|
39 | | -```pyhton |
40 | | ->>> func = lambda n:1 if n == 0 else n * func(n-1) |
41 | | ->>> func(5) |
42 | | -120 |
| 72 | +```python |
| 73 | +>>> def demo_func(**kw): |
| 74 | +... print(kw) |
| 75 | +... |
| 76 | +>>> demo_func(a=10, b=20, c=30) |
| 77 | +{'a': 10, 'b': 20, 'c': 30} |
43 | 78 | ``` |
44 | 79 |
|
45 | | -或者 |
| 80 | +**案例六**:必选参数一定要在可选参数的前面,不然运行时会报错 |
46 | 81 |
|
47 | 82 | ```python |
48 | | ->>> f = lambda func, n: 1 if n == 0 else n * func( func, n - 1 ) |
49 | | ->>> f(f,4) |
50 | | -24 |
| 83 | +>>> def demo_func(a=1, b): |
| 84 | +... print(a, b) |
| 85 | +... |
| 86 | + File "<stdin>", line 1 |
| 87 | +SyntaxError: non-default argument follows default argument |
| 88 | +>>> |
| 89 | +>>> def demo_func(a, b=1): |
| 90 | +... print(a, b) |
| 91 | +... |
| 92 | +>>> |
51 | 93 | ``` |
52 | 94 |
|
53 | | -从以上示例来看,lambda 表达式和常规的函数相比,写法比较怪异,可读性相对较差。除了可以直接运行之外,好像并没有其他较为突出的功能,为什么在今天我们要介绍它呢? |
| 95 | +**案例七**:可变位置参数一定要在可变关键字参数前面,不然运行时也会报错 |
| 96 | + |
| 97 | +```python |
| 98 | +>>> def demo_func(**kw, *args): |
| 99 | + File "<stdin>", line 1 |
| 100 | + def demo_func(**kw, *args): |
| 101 | + ^ |
| 102 | +SyntaxError: invalid syntax |
| 103 | +>>> |
| 104 | +>>> def demo_func(*args, **kw): |
| 105 | +... print(args, kw) |
| 106 | +... |
| 107 | +>>> |
| 108 | +``` |
| 109 | + |
| 110 | +**案例八**:可变参数可以放在位置参数前面,但是在调用时,必须要指定参数名来传入 位置参数值 ,否则 会报错 |
| 111 | + |
| 112 | +```python |
| 113 | +>>> def demo_func(*args, b): |
| 114 | +... print(args) |
| 115 | +... print(b) |
| 116 | +... |
| 117 | +>>> demo_func(1, 2, 100) |
| 118 | +Traceback (most recent call last): |
| 119 | + File "<stdin>", line 1, in <module> |
| 120 | +TypeError: demo_func() missing 1 required keyword-only argument: 'b' |
| 121 | +>>> |
| 122 | +>>> demo_func(1, 2, b=100) |
| 123 | +(1, 2) |
| 124 | +100 |
| 125 | +``` |
| 126 | + |
| 127 | +**案例九**:关键字参数则不一样,关键字参数一定得放在最后,下面三个示例中,不管关键字参数后面接位置参数,还是默认参数,还是可变参数,都会报错。 |
| 128 | + |
| 129 | +```python |
| 130 | +>>> def demo_func(**kw, a): |
| 131 | + File "<stdin>", line 1 |
| 132 | + def demo_func(**kw, a): |
| 133 | + ^ |
| 134 | +SyntaxError: invalid syntax |
| 135 | +>>> |
| 136 | +>>> def demo_func(**kw, a=1): |
| 137 | + File "<stdin>", line 1 |
| 138 | + def demo_func(**kw, a=1): |
| 139 | + ^ |
| 140 | +SyntaxError: invalid syntax |
| 141 | +>>> |
| 142 | +>>> def demo_func(**kw, *args): |
| 143 | + File "<stdin>", line 1 |
| 144 | + def demo_func(**kw, *args): |
| 145 | + ^ |
| 146 | +SyntaxError: invalid syntax |
| 147 | +``` |
| 148 | + |
| 149 | +**案例十**:将上面的知识点串起来,四种参数类型可以在一个函数中出现,但一定要注意顺序 |
| 150 | + |
| 151 | +```python |
| 152 | +def demo_func(arg1, arg2=10, *args, **kw): |
| 153 | + print("arg1: ", arg1) |
| 154 | + print("arg2: ", arg2) |
| 155 | + print("args: ", args) |
| 156 | + print("kw: ", kw) |
| 157 | +``` |
| 158 | + |
| 159 | +试着调用这个函数,输出如下: |
| 160 | + |
| 161 | +```python |
| 162 | +>>> demo_func(1,12, 100, 200, d=1000, e=2000) |
| 163 | +arg1: 1 |
| 164 | +arg2: 12 |
| 165 | +args: (100, 200) |
| 166 | +kw: {'d': 1000, 'e': 2000} |
| 167 | +``` |
| 168 | + |
| 169 | + |
| 170 | + |
| 171 | +**案例十一**:使用单独的 `*`,可以后面的位置参数变成关键字参数,关键字参数在你传参时,必须要写参数名,不然会报错。 |
| 172 | + |
| 173 | +```python |
| 174 | +>>> def demo_func(a, b, *, c): |
| 175 | +... print(a) |
| 176 | +... print(b) |
| 177 | +... print(c) |
| 178 | +... |
| 179 | +>>> |
| 180 | +>>> demo_func(1, 2, 3) |
| 181 | +Traceback (most recent call last): |
| 182 | + File "<stdin>", line 1, in <module> |
| 183 | +TypeError: demo_func() takes 2 positional arguments but 3 were given |
| 184 | +>>> |
| 185 | +>>> demo_func(1, 2, c=3) |
| 186 | +1 |
| 187 | +2 |
| 188 | +3 |
| 189 | +``` |
| 190 | + |
| 191 | +## 3. 传参的坑 |
| 192 | + |
| 193 | +函数参数传递的是实际对象的内存地址。如果参数是引用类型的数据类型(列表、字典等),在函数内部修改后,就算没有把修改后的值返回回去,外面的值其实也已经发生了变化。 |
| 194 | + |
| 195 | +```python |
| 196 | +>>> def add_item(item, source_list): |
| 197 | +... source_list.append(item) |
| 198 | +... |
| 199 | +>>> alist = [0,1] |
| 200 | +>>> add_item(2, alist) |
| 201 | +>>> alist |
| 202 | +[0, 1, 2] |
| 203 | +``` |
54 | 204 |
|
55 | | -首先我们要知道 lambda 是一个表达式,而不是一个语句。正因为这个特点,我们可以在一些特殊的场景中去使用它。具体是什么场景呢?接下来我们会介绍到几个非常好用的内置函数。 |
|
0 commit comments