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