Skip to content

Commit 6655a9e

Browse files
author
王炳明
committed
update
1 parent 9db8c1b commit 6655a9e

10 files changed

Lines changed: 1220 additions & 1077 deletions

File tree

source/c05/c05_01.md

Lines changed: 1 addition & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# 5.1 【基础】普通函数
1+
# 5.1 【基础】普通函数创建与调用
22

33
函数是一种仅在调用时运行的代码块。您可以将数据(称为参数)传递到函数中,然后由函数可以把数据作为结果返回。
44

@@ -51,51 +51,6 @@ average = get_average(2, 6)
5151
print(average) # output: 4
5252
```
5353

54-
## 3. 函数的参数
55-
56-
函数,在定义的时候,可以有参数的,也可以没有参数。
57-
58-
参数在定义的时候,根据是否有指定默认值,可以分为
59-
60-
1. 必选参数,也叫位置参数
61-
2. 可选参数,也叫默认参数
62-
63-
比如下边这个函数,a 是必选参数,b 是可选参数。如果你调用了这个参数,
64-
65-
```python
66-
def demo_func(a, b=10):
67-
return a+b
68-
```
69-
70-
那么 a 是必须要指定的,而 b 可以指定也可以不指定,不指定的话,默认为10
71-
72-
```python
73-
>>> def demo_func(a, b=10):
74-
... return a+b
75-
...
76-
>>> demo_func(10) # 不指定 b ,默认为10
77-
20
78-
>>> demo_func(10, 5) # 指定 b=5
79-
15
80-
```
81-
82-
如果一个函数有多个位置参数,你在调用指定参数时,需要注意顺序
83-
84-
```python
85-
>>> def print_profile(name, age):
86-
... return f"我的名字叫{name},今年{age}岁了"
87-
...
88-
>>> print_profile("王炳明", 27)
89-
'我的名字叫王炳明,今年27岁了'
90-
```
91-
92-
如果参数太多,你不想太花精力去注意顺序,可以在指定参数时,附上参数名,比如这样:
93-
94-
```python
95-
>>> print_profile(age=27, name="王炳明")
96-
'我的名字叫王炳明,今年27岁了'
97-
```
98-
9954
## 4. 函数的返回
10055

10156
函数的返回值,可以是多种多样的,非常灵活:
@@ -132,19 +87,3 @@ def decorator(func):
13287
return wrapper
13388
```
13489

135-
## 5. 传参时应注意
136-
137-
在使用函数时,有几个小坑,会让新人犯了错还摸不着头脑。
138-
139-
函数参数传递的是实际对象的内存地址。如果参数是引用类型的数据类型(列表、字典等),在函数内部修改后,就算没有把修改后的值返回回去,外面的值其实也已经发生了变化。
140-
141-
```python
142-
>>> def add_item(item, source_list):
143-
... source_list.append(item)
144-
...
145-
>>> alist = [0,1]
146-
>>> add_item(2, alist)
147-
>>> alist
148-
[0, 1, 2]
149-
```
150-

source/c05/c05_02.md

Lines changed: 178 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,55 +1,204 @@
1-
# 5.2 【基础】匿名函数
1+
# 5.2. 【基础】11个案例讲解函数参数
22

3-
匿名函数(英语:anonymous function)是指一类无需定义标识符(函数名)的函数。通俗来说呢,就是它可以让我们的函数,可以不需要函数名。
3+
## 1. 参数分类
44

5-
正常情况下,我们定义一个函数,使用的是 `def` 关键字,而当你学会使用匿名函数后,替代 `def` 的是 `lambda`
5+
函数,在定义的时候,可以有参数的,也可以没有参数
66

7-
这边使用`def``lambda` 分别举个例子,你很快就能理解。
7+
在 Python 中参数的种类,大概可以分为四种
8+
9+
1. `必选参数`,也叫`位置参数`,调用函数时一定指定的参数,并且在传参的时候必须按函数定义时的顺序来
10+
2. `可选参数`,也叫`默认参数`,调用函数时,可以指定也可以不指定,不指定就默认的参数值来。
11+
3. `可变参数`,就是参数个数可变,可以是 0 个或者任意个,但是传参时不能指定参数名,通常使用 `*args` 来表示。
12+
4. `关键字参数`,就是参数个数可变,可以是 0 个或者任意个,但是传参时必须指定参数名,通常使用 `**kw` 来表示
13+
14+
## 2. 十个案例
15+
16+
**案例一**:在下面这个函数中, a 是位置参数,必须要指定的
817

918
```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
1431

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
1740
```
1841

19-
从上面的示例,我们可以看到匿名函数直接运行,省下了很多行的代码,有没有?
42+
**案例三**:在下面这个函数中, name 和 age 都是位置参数,在调用指定参数时,需要注意顺序
2043

21-
接下来,我们的仔细看一下它的用法
44+
```python
45+
>>> def print_profile(name, age):
46+
... return f"我的名字叫{name},今年{age}岁了"
47+
...
48+
>>> print_profile("王炳明", 27)
49+
'我的名字叫王炳明,今年27岁了'
50+
```
2251

23-
带 if/else
52+
如果参数太多,你不想太花精力去注意顺序,可以在指定参数时,附上参数名,比如这样:
2453

2554
```python
26-
>>>( lambda x, y: x if x < y else y )( 1, 2 )
27-
1
55+
>>> print_profile(age=27, name="王炳明")
56+
'我的名字叫王炳明,今年27岁了'
2857
```
2958

30-
嵌套函数
59+
**案例四**:在下面这个函数中,`args` 参数和上面的参数名不太一样,在它前面有一个 `*`,这就表明了它是一个可变参数,可以接收任意个数的不指定参数名的参数。
3160

3261
```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)
3568
```
3669

37-
递归函数
70+
**案例五**:在下面这个函数中,`kw` 参数和上面的 `*args` 还多了一个 `*` ,总共两个 `**` ,这个意思是 `kw` 是一个可变关键字参数,可以接收任意个数的带参数名的参数。
3871

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}
4378
```
4479

45-
或者
80+
**案例六**:必选参数一定要在可选参数的前面,不然运行时会报错
4681

4782
```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+
>>>
5193
```
5294

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+
```
54204

55-
首先我们要知道 lambda 是一个表达式,而不是一个语句。正因为这个特点,我们可以在一些特殊的场景中去使用它。具体是什么场景呢?接下来我们会介绍到几个非常好用的内置函数。

0 commit comments

Comments
 (0)