1# author: wangy
2# date: 2024/7/9
3# description:
4"""
5python 函数的几个小🌰️
61. 定义函数的关键字 `def`
72. 函数的返回值 `None`和return语句 斐波那契数
83. 解包赋值表达式
94. 函数的形参列表
10 - 位置参数
11 - 关键字参数
12 - 特殊参数(元组和字典)
135. 解包表达式作为实参
146. Lambda表达式作为实参
15"""
16
17
18def func(length, width):
19 s = length * width
20 print(f'Square of rectangle is {s}.')
21
22
23# 函数可以直接赋值给变量
24mf = func
25mf(5, 3)
26
27
28def __fib(limit):
29 """
30 - fibonacci斐波那契数列
31 - 形参: limit: 最大数限制
32 """
33 a, b = 0, 1
34 while a < limit:
35 print(a, end=' ')
36 # python的解包赋值特性
37 a, b = b, a + b
38 print(end='\n')
39
40
41__fib(100)
42# 内置变量 "__doc__", 可以查看文档
43print(__fib.__doc__)
44
45
46def __fib2(limit):
47 a, b = 0, 1
48 res = []
49 while a < limit:
50 res.append(a)
51 a, b = b, a + b
52 return res
53
54
55print(__fib2(1000))
56
57
58def __quit(retry, prompt='ready to quit? y/n', reminder='Please try again!'):
59 """
60 形参列表,有多种形式的参数:
61 1. 不带默认值的参数,是必填参数
62 2. 带默认值的参数是可选参数
63 """
64 while True:
65 reply = input(prompt)
66 if reply in ('y', 'yes', 'yep', 'ye'):
67 return True
68 elif reply in ('n', 'no', 'nope'):
69 return False
70 retry -= 1
71 if retry < 0:
72 raise ValueError('invalid user response')
73 print(reminder)
74
75
76print('\n')
77
78# 仅仅使用必填参数
79# print(__quit(2))
80# 使用必填和部分可选参数
81# print(__quit(2, 'Do you really want to quit(y/n)?'))
82# 使用全部参数
83print(__quit(2, 'Ready to quit(y/n)?', 'Please input yes or no.'))
84"""
85以上调用函数的方式全部是位置参数(posotional argument)
86
87此外, 还可以使用关键字参数来调用函数
88
89注意, 关键字参数必须在位置参数后面
90"""
91
92print(__quit(2, prompt='quit(y/n)?'))
93
94
95# 特殊参数
96def __sfunc(*args, **kwargs):
97 """
98 特殊参数 元组tuple 和字典dict
99 """
100 print(args, end='\n')
101 print(kwargs)
102
103
104__sfunc((1, 2), (3, 4), name='mask', age='53', nation='US')
105
106# 如果实参单独定义,调用函数时需要解包
107a_list = ('apple', 'orange', 'grape', 'watermelon')
108a_tuple = {
109 'title': 'data structure and algorithm analysis',
110 'sub-title': 'descripted by Java',
111 'publish': 'machine press'
112}
113'''
114这里如果直接使用 `__sfunc(a_list, a_tuple)`程序并不会出错.
115
116不过请看上一例, 这里的处理是将l和m作为元组的参数处理的.
117(这意为着, 函数`__sfunc`的形参数是任意可变的)
118
119所以必须要**解包**实参列表, 才能将`l`和`m`分别作为位置参数.
120'''
121__sfunc(*a_list, **a_tuple)
122
123
124# 参数使用的标记 / 和 *
125def __fargtag(c=8, /, prompt='input a integer:', *, remainder='func done'):
126 """
127 计算c的阶乘
128
129 `c` before '/' means it's a positional argument
130
131 `prompt` after '/' means it's a positional or keyword argument
132
133 `remainder` after '*' means it's a keyword arguments
134 """
135 c = int(input(prompt))
136 r = 1
137 while c > 0:
138 r = r * c
139 c = c - 1
140 print(remainder, r, end='\n')
141 return r
142
143
144__fargtag(remainder='final result is ')
145
146
147def __argfunc(leng: int, wid: int):
148 return leng * wid
149
150
151def __cal(f: __argfunc, prompt='this func show a rectangle\'s square'):
152 print(prompt)
153 length = input('pls input length of retangle:')
154 wid = input('pls input width of rectangle:')
155 s = f(int(length), int(wid))
156 print(f'Square is {s}\n')
157
158
159__cal(__argfunc)
160# or
161__cal(f=lambda x, y: __argfunc(x, y))
162
163# Lambda表达式
164"""
165lambda表达式是一种简洁的方式来定义匿名函数.
166
167lambda表达式可以在需要函数对象的任何地方使用, 并且通常用于简单的函数功能.
168
169sort方法支持对paris列表的元组数据排序, 它的关键字参数key由一个Lambda表达式提供.
170
171Lambda的内涵是: 按照参数p(可以推导出元组)的索引为1的元素排序.
172
173已知索引为1的元素是字符串, 所以即按照字符串的字母表顺序排序.
174
175故排序后的paries是
176
177[(4, 'four'), (1, 'one'), (3, 'three'), (2, 'two')]
178"""
179
180paris = [(1, 'one'), (2, 'two'), (3, 'three'), (4, 'four')]
181paris.sort(key=lambda p: p[1])
182print(paris)
183
184
185# 完整的函数声明,包括参数数据类型,返回值类型
186def full_dunc_def(arg: int,
187 arg2: str = 'optional arg',
188 arg3: tuple = (1, 'one')) -> str:
189 """python函数的完整声明
190
191 Args:
192 arg (int):
193 arg2 (str, optional): Defaults to 'optional arg'.
194 arg3 (tuple, optional): Defaults to (1, 'one').
195
196 Returns:
197 str: 声明为返回str, 但是python不强制返回值必须和声明一致.
198 """
199 print(arg2)
200 print(arg3, end='\n')
201 # return 类型和函数声明类型不是强制一致
202 return arg3
203
204
205print(full_dunc_def(1))