day08 回顾:
两个容器: 集合set 和 固定集合 frozenset 可变 不可变 集合的创建: 构造函数: set() set(range(10))) 字面值: {1, 2, 3, 4} 集合推导式: {x ** 2 for x in range(1, 10)} 固定集合的创建: 构造函数: frozenset() frozenset(range(10)) 集合的运算: &交集 |并集 ^对称补集 -补集 <子集 >超集 ==相等 !=不等 <=子集或相等 >= 超集或相等 in / not in集合的方法:
S.add(x) 增加 S.remove(x) 删除 S.discard(x) 删除(但不提示错误) S.clear() S.pop() 删除随机元素 S.copy()能用容器类的函数
len(x) min(x) max(x) ..... 函数 function 函数是面向过程编程的最小单位两条语句:
def 语句 语法: def 函数名(形参变量1, 形参变量2, ....): 语句块 作用: 创建函数, 用函数名绑定这个函数调用表达式:
函数名(实参1, 实参2, ....)return 语句
作用: 结束当前函数的执行,返回到调用此函数的地方 格式: return [表达式] day09 笔记: python函数的参数传递(把数据给函数) 传递方式: 位置传参 序列传参 关键字传参 字典关键字传参位置传参:
实际参数(实参)的对应关系与形式参数(形参)的对应关系是按位置 来依次对应的 示意: def mymin(a, b, c): passmymin( 1, 2, 3)
说明: 实际参数和形式参数通过位置进行传递和匹配 实际参数的个数必须与形式参数的个数相同 示例见: positional_give_args.py
1 # positional_give_args.py 2 3 4 # 此示例示意位置传参 5 def myfun1(a, b, c): 6 '''这是一个函数传参的示例''' 7 print("a的值是:", a) 8 print("b的值是:", b) 9 print("c的值是:", c) 10 11 myfun1(1, 2, 3) # 1-->a 2-->b 3-->c 12 myfun1(4, 5, 6) 13 14 15 16
示例见: sequence_give_args.py
1 2 3 # 此示例示意序列传参 4 def myfun1(a, b, c): 5 '''这是一个函数传参的示例''' 6 print("a的值是:", a) 7 print("b的值是:", b) 8 print("c的值是:", c) 9 10 L1 = [11, 22, 33] 11 t2 = (100, 200, 300) 12 s3 = "ABC" 13 14 myfun1(L1[0], L1[1], L1[2]) # L1[0](将11)---> a, L1[1]--->b, ... 15 myfun1(*L1) # 等同于myfunc(L1[0], L1[1], L1[2]) 16 myfun1(*t2) 17 myfun1(*s3) 18 19 20
关键字传参:
关键字传参是指传参时,按着形参的名称给形参赋值 实参和形参按名称进行匹配示例见:
keywords_give_args.py1 2 3 # 此示例示意 关键字 传参 4 def myfun1(a, b, c): 5 '''这是一个函数传参的示例''' 6 print("a的值是:", a) 7 print("b的值是:", b) 8 print("c的值是:", c) 9 10 myfun1(c=33, b=22, a=11) 11 myfun1(b=2, a=1, c=3) 12 13
字典关键字传参:
是指实参为字典,将字典用**拆解后进行关键字传参的传参方式示例见: dict_keyword_give_args.py
1 2 3 # 此示例示意 字典关键字 传参 4 def myfun1(a, b, c): 5 '''这是一个函数传参的示例''' 6 print("a的值是:", a) 7 print("b的值是:", b) 8 print("c的值是:", c) 9 10 d1 = {'c': 33, 'a': 11, 'b': 22} 11 myfun1(c=d1['c'], a=d1['a'], b=d1['b']) # 33--->c , 11--->a ... 12 13 myfun1(**d1) # 拆解字典,再按关键字传参方式传递 14 15 16
1 # 练习: 2 # 已知有列表: 3 # L = [1, 2, True, None, 3.14] 4 # 调用print函数,打印用'#'号分隔的文字信息到终端上 5 # print(....) # 打印 1#2#True#None#3.14 6 7 8 9 L = [1, 2, True, None, 3.14] 10 11 print(*L, sep="#") # 打印 1#2#True#None#3.14 12 # 等同于print(1, 2, True, None, 3.14, sep='#') 13 14
示例: def myfun1(a, b, c): pass myfun1(100, c=300, b=200) # 正确 myfun1(c=300,b=200, 100) # 错的 myfun1(100, *[200, 300]) # 正确 myfun1(*[100, 200], 300) # 正确 myfun1(100, *[200], 300) # 正确 myfun1(100, **{'c':300, 'b':200}) # 正确 myfun1(**{'c':300, 'b':200}, a=100) # 正确
可变 和不可变类型的容器作为实参传递的区别:
可变类型的实参作为参数传递时,在函数内部可以改变容器内的数据示例见:
list_as_args.py list_as_args2.py1 # list_as_args.py 2 3 # 此示例示意,当函数的实参为可变数据类型时,在函数内部可以改为 4 # 容器的内容 5 6 L = [1, 2, 3, 4] 7 t = (1.1, 2.2, 3.3, 4.4) 8 9 def append_5(x): 10 # x.append(5) 11 x += (5,) 12 print('x=', x) # 1.1, 2.2, 3.3, 4.4, 5 13 14 append_5(L) 15 print(L) # [1, 2, 3, 4, 5] 16 17 append_5(t) 18 print(t) # (1.1, 2.2, 3.3, 4.4) 19 20 21 22
1 # list_as_args2.py 2 3 4 # 写一个函数,此函数读取用户输入的数据,最后保存于全局变量的列表 5 # L中, 当用户输入小于零的数时结束输入 6 L = [] 7 def input_number(L1): 8 while True: 9 x = int(input('请输入:')) 10 if x < 0: 11 break 12 L1.append(x) 13 14 input_number(L) 15 print(L) 16 input_number(L) 17 print(L) 18 19 20 21 22 23 24
----- 以下讲函数的定义(创建函数的def语句的形参列表)----
函数的缺省参数: 语法: def 函数名(形参名1=默认实参1, 形参名2=默认实参2, ...): 语句块 示例见: default_args.py1 # default_args.py 2 3 4 def info(name, age=1, address='不详'): 5 print(name,'今年', age, '岁,家庭住址:', address) 6 7 info("魏明择", 35, '北京市朝阳区') 8 info("tarena", 15) 9 info("小飞") 10
说明:
缺省参数必须自右至左依次存在,如果一个参数有缺省参数,则其 右侧的所有参数都必须有缺省参数,如: def test_fn(a, b=10, c): 是错的 缺省参数可以有0个,1个或多个,甚至全部都有缺省参数 示例: def fn(a, b=10, c): # 错误 pass def fn(a=0, b=10, c=20): # 这是对的 pass练习:
写一个函数myadd,此函数可以计算两个数,三个数及四个数的和 def myadd(...): ... print(myadd(10, 20)) # 30 print(myadd(100, 200, 300)) # 600 print(myadd(1, 2, 3, 4)) # 101 # 练习: 2 # 写一个函数myadd,此函数可以计算两个数,三个数及四个数的和 3 # def myadd(...): 4 # ... 5 6 # print(myadd(10, 20)) # 30 7 # print(myadd(100, 200, 300)) # 600 8 # print(myadd(1, 2, 3, 4)) # 10 9 10 11 def myadd(a, b, c=0, d=0): 12 return a + b + c + d 13 14 print(myadd(10, 20)) # 30 15 print(myadd(100, 200, 300)) # 600 16 print(myadd(1, 2, 3, 4)) # 10 17 18
位置形参
语法: def 函数名(形参名1, 形参名2, ...): 语句块星号元组形参:
语法: def 函数名(*元组形参名): 语句块 作用: 收集多余的位置传参 说明: 在一个函数定义中元组形参名最多只能有一个,一般命名为'args' 示例见: star_tuple_args.py练习:
写一个函数 mysum 可以传入任意个数字实参,返回所有实参的和 def mysum(*args): ... print(mysum(1, 2, 3, 4)) # 10 print(mysum(1, 3, 5, 7, 9)) # 251 # 练习: 2 # 写一个函数 mysum 可以传入任意个数字实参,返回所有实参的和 3 # def mysum(*args): 4 # ... 5 6 # print(mysum(1, 2, 3, 4)) # 10 7 # print(mysum(1, 3, 5, 7, 9)) # 25 8 9 10 # 方法1 11 # def mysum(*args): 12 # s = 0 13 # for x in args: 14 # s += x 15 # return s 16 17 # 方法2 18 def mysum(*args): 19 return sum(args) 20 21 print(mysum(1, 2, 3, 4)) # 10 22 print(mysum(1, 3, 5, 7, 9)) # 25 23 24
1 # named_keyword_args.py 2 3 4 # 此示例示意在函数形参中定义命名关键字形参,强制让函数调用 5 # 使用命名关键字传参: 6 7 def func1(a, b, *, c, d): 8 print(a, b, c, d) 9 10 # func1(1, 2, 3, 4) # 报错 11 func1(1, 2, c=30, d=40) 12 func1(a=10, b=20, c=30, d=40) 13 14
1 # named_keyword_args.py 2 3 4 # 此示例示意在函数形参中定义命名关键字形参,强制让函数调用 5 # 使用命名关键字传参: 6 7 def func1(a, b, *args, c, d): 8 print(a, b, args, c, d) 9 10 # func1(1, 2, 3, 4) # 报错 11 func1(1, 2, c=30, d=40) 12 func1(a=10, b=20, c=30, d=40) 13 func1(1, 2, 3, 4, d=400, c=300) 14 15 func1(*"ABCDEFG", **{'c':999, 'd':888}) 16 17 18
1 # star_dict_args.py 2 3 # 此示例示意用双星号字典形参接收多余的关键字传参 4 5 def func(**kwargs): 6 print("关键字传参的个数是:", len(kwargs)) 7 print("kwargs=", kwargs) 8 9 func(name='weimingze', age=35, address='北京市朝阳区') 10 func(a=1, b=2) 11
1 # star_tuple_args.py 2 3 # 此示例示意星号元组形参的定义和使用 4 5 def func(*args): 6 print("实参个数是:", len(args)) 7 print('args=', args) 8 9 func(1, 2, 3, 4) 10 func(5, 6, 7, 8, 'A', 'B', 'C', 'D') 11 func() 12
函数的参数说明:
位置形参,缺省参数,星号元组形参,双星号字典形参可以混合使用函数参数自左至右的顺序为:
1. 位置形参 2. 星号元组形参 3. 命名关键字形参 4. 双星号字典形参示例: def fn(a, b=20, *args, c=30, d=40, **kwargs): pass fn(1) fn(100, 200, 300, 400, c='C', d='D', e='E')
练习: 已知内建函数max帮助文档为: max(...) max(iterable) -> value max(arg1, arg2, *args) -> value 仿造 max写一个mymax函数,功能与max完全相同 (要求不允许调用max) 测试程序如下: print(mymax([6, 8, 3, 5])) # 8 print(mymax(100, 200)) # 200 print(mymax(1, 3, 5, 9, 7)) # 91 # 练习: 2 # 已知内建函数max帮助文档为: 3 # max(...) 4 # max(iterable) -> value 5 # max(arg1, arg2, *args) -> value 6 # 仿造 max写一个mymax函数,功能与max完全相同 7 # (要求不允许调用max) 8 # 测试程序如下: 9 # print(mymax([6, 8, 3, 5])) # 8 10 # print(mymax(100, 200)) # 200 11 # print(mymax(1, 3, 5, 9, 7)) # 9 12 13 14 # def mymax(a, *args): 15 def mymax(*args): 16 # print("args=", args) 17 if len(args) == 1: # 判断是否是一个可迭代参数的情况 18 L = args[0] # 一定绑定一个可迭代对象 19 zuida = L[0] # 假设第一个元素最大 20 for x in L: 21 if x > zuida: 22 zuida = x 23 return zuida 24 else: # 否则有多个参数的情况 25 zuida = args[0] 26 for x in args: 27 if x > zuida: 28 zuida = x 29 return zuida 30 31 32 print(mymax([6, 8, 3, 5])) # 8 33 print(mymax(100, 200)) # 200 34 print(mymax(1, 3, 5, 9, 7)) # 9 35 36 37 38
1 # 练习: 2 # 已知内建函数max帮助文档为: 3 # max(...) 4 # max(iterable) -> value 5 # max(arg1, arg2, *args) -> value 6 # 仿造 max写一个mymax函数,功能与max完全相同 7 # (要求不允许调用max) 8 # 测试程序如下: 9 # print(mymax([6, 8, 3, 5])) # 8 10 # print(mymax(100, 200)) # 200 11 # print(mymax(1, 3, 5, 9, 7)) # 9 12 13 14 def mymax(a, *args): 15 if len(args) == 0: # 判断是否是一个可迭代参数的情况 16 L = a # 一定绑定一个可迭代对象 17 zuida = L[0] # 假设第一个元素最大 18 for x in L: 19 if x > zuida: 20 zuida = x 21 return zuida 22 else: # 否则有多个参数的情况 23 zuida = a 24 for x in args: 25 if x > zuida: 26 zuida = x 27 return zuida 28 29 30 print(mymax([6, 8, 3, 5])) # 8 31 print(mymax(100, 200)) # 200 32 print(mymax(1, 3, 5, 9, 7)) # 9 33 34 35 36
局部变量说明:
在函数内部赋值语句不会对全局变量造成影响 局部变量只能在其被声明的函数内部访问,而全局变量可以在整数模 块范围内访问 示例见: global_local.py1 # global_local.py 2 3 # 此示例示意全局变量的定义和局部变量的定义 4 a = 100 5 b = 200 6 c = 9999999 7 def fx(c): 8 a = 1 # 创建局部变量,并非改变全局变量 9 d = 400 10 print(a, b, c, d) 11 12 fx(300) 13 print('a=', a) # 100 14 print('b=', b) 15 print('c=', c)
globals 和 locals 函数:
globals() 返回当前全局作用域内变量的字典 locals() 返回当前局部作用域内变量的字典示例见: globals_and_locals.py
1 # globals_and_locals.py 2 3 4 # 此示例示意globals 和 locals函数的使用方法 5 a = 1 6 b = 2 7 c = 3 8 def fn(c, d): 9 e = 300 10 # 此处有多少个局部变量? 11 print("locals()返回:", locals()) 12 # 此处有多少个全局变量? 13 print("globals() 返回:", globals()) 14 print(c) # 100 15 print(globals()['c']) # 3 16 17 18 fn(100, 200) 19
1 # 1. 算出 100 ~ 999 以内的水仙花数(Narcissistic number) 2 # 水仙花数是指百位的3次方加上十位的3次方加上个位的3次方 3 # 等于原数的整数 4 # 例如: 153 = 1**3 + 5**3 + 3**3 5 # 答案: 153, 370, ... 6 7 # 方法1 8 # for x in range(100, 1000): 9 # # 拆出百位,十位,个位 10 # bai = x // 100 # 百位 11 # shi = x % 100 // 10 # 十位 12 # ge = x % 10 # 个位 13 # if x == bai ** 3 + shi ** 3 + ge ** 3: 14 # print(x) # 满足条件的水仙花数 15 16 # 方法2, 将数字转为字符串 17 # for x in range(100, 1000): 18 # s = str(x) 19 # bai = int(s[0]) 20 # shi = int(s[1]) 21 # ge = int(s[2]) 22 # if x == bai ** 3 + shi ** 3 + ge ** 3: 23 # print(x) # 满足条件的水仙花数 24 25 # 方法3 26 for bai in range(1, 10): 27 for shi in range(0, 10): 28 for ge in range(10): 29 # print(bai, shi, ge) 30 x = bai * 100 + shi * 10 + ge 31 if x == bai ** 3 + shi ** 3 + ge ** 3: 32 print(x)
1 # 2. 完全数: 2 # 1 + 2 + 3 = 6 (6为完全数) 3 # 1, 2, 3都为6的因数(能被一个数x整除的数为y,则y为x的因数) 4 # 1 x 6 = 6 5 # 2 x 3 = 6 6 # 完全数是指除自身以外的所有因数之和相加等于自身的数 7 # 求4~5个完全数,并打印 8 # 答案: 9 # 6 10 # 28 11 # 496 12 # ... 13 14 def is_perfect_number(x): 15 '''此函数判断x是否为完全数,如果是返回True,否则返回False''' 16 L = [] # 创建一个列表,用来存放x所有的因数 17 for i in range(1, x): 18 if x % i == 0: # 整除了,i则一定是x的因数 19 L.append(i) 20 if sum(L) == x: # 是完全数 21 return True 22 return False 23 24 def main(): 25 i = 2 26 while True: 27 # 如果i是完全数,则打印i的值 28 if is_perfect_number(i): 29 print(i) 30 31 i += 1 32 33 main() 34
1 # 3. 写一个myrange()函数,参数可以传1~3个,实际意义同range函数 2 # 规则相同,此函数返回符合range(...) 函数规则的列表 3 # 如: 4 # L = myrange(4) 5 # print(L) # [0, 1, 2, 3] 6 # L = myrange(4, 6) 7 # print(L) # [4, 5] 8 # L = myrange(1, 10, 3) 9 # print(L) # [1, 4, 7] 10 11 12 def myrange(start, stop=None, step=None): 13 if stop is None: # if not stop: 14 stop = start 15 start = 0 16 if step is None: 17 step = 1 18 # 开始,结束和步长都已确定 19 # return [x for x in range(start, stop, step)] 20 if step > 0: # 正向 21 L = [] 22 while start < stop: 23 L.append(start) 24 start += step 25 return L 26 elif step < 0: 27 L = [] 28 while start > stop: 29 L.append(start) 30 start += step 31 return L 32 33 L = myrange(4) 34 print(L) # [0, 1, 2, 3] 35 L = myrange(4, 6) 36 print(L) # [4, 5] 37 L = myrange(1, 10, 3) 38 print(L) # [1, 4, 7] 39 40 L2 = myrange(10, 0, -2) 41 print(L2) 42 43 44
1 2 # 3. 改写之前的学生信息管理程序: 3 # 用两个函数来封装功能的代码块 4 # 函数1: input_student() # 返回学生信息字典的列表 5 # 函数2: output_student(L) # 打印学生信息的表格 6 7 def input_student(): 8 L = [] # 创建一个列表,准备存放学生数据的字典 9 while True: 10 n = input("请输入姓名: ") 11 if not n: # 如果用户输入空字符串就结束输入 12 break 13 a = int(input("请输入年龄: ")) 14 s = int(input("请输入成绩: ")) 15 d = {} # 一定要每次都创建一个新的字典 16 d['name'] = n 17 d['age'] = a 18 d['score'] = s 19 L.append(d) # 把d加入列表中L 20 return L 21 22 def output_student(L): 23 print("+---------------+----------+----------+") 24 print("| 姓名 | 年龄 | 成绩 |") 25 print("+---------------+----------+----------+") 26 for d in L: 27 name = d['name'] 28 age = str(d['age']) # 转为字符串 29 score = str(d['score']) # 转为字符串 30 print("|%s|%s|%s|" % (name.center(15), 31 age.center(10), 32 score.center(10))) 33 print("+---------------+----------+----------+") 34 35 36 # infos = input_student() 37 # print(infos) # 打印列表[{...}, {...}] 38 # output_student(infos) # 根据实参infos打印表格 39 40 def main(): 41 infos = [] # 此列表用于保存学生数据 42 while True: 43 print(" 1) 添加学生信息") 44 print(" 2) 显示学生信息") 45 print(" q) 退出") 46 s = input("请选择: ") 47 if s == '1': 48 infos += input_student() 49 elif s == '2': 50 output_student(infos) 51 elif s == 'q': 52 break 53 54 55 main() 56