day09回顾:
函数的参数:
实参(给)
传递方式:
位置传参
序列传参
关键字传参
字典关键字传参
形参(接)
缺省参数(default argument)
def fx(a=0, b=2, c=3):
...
形参的定义方式(四种)
位置形参
星号元组形参
命名关键字形参
双星号字典形参
def fx(a, b, *args, c, d, **kwargs):
...
全局变量和局部变量
局部变量 local
全局变量 global
创建用赋值语句
销毁用del 语句
两个函数 globals(), locals() 返回全局变量和局部变量的字典
day10 笔记
函数变量
函数名是变量,它在创建函数时绑定一个函数
示例:
def f1():
print("f1函数被调用")
f2 = f1 # 两个变量同时绑定一个函数
f2() # f1函数被调用
示例2:
def f1():
print("f1")
def f2():
print("f2")
f1, f2 = f2, f1
f1() # f2
一个函数可以作为另一个函数的实参传递
示例见:
function_as_args.py
function_as_args2.py
1 # function_as_args.py 2 3 4 def f1(): 5 print("f1被调用") 6 7 def f2(): 8 print("f2被调用!") 9 10 def fx(fn): 11 print(fn) 12 fn() # ??? 13 14 fx(f1) 15 fx(f2) 16 17 18 19 20 21 22 23
1 # function_as_args2.py 2 3 def goodbye(L): 4 for x in L: 5 print("再见:", x) 6 7 def operator(fn, L): 8 fn(L) 9 10 operator(goodbye, ['Tom', 'Jerry', 'Spike'])
练习:
看懂下列代码:
def myinput(fn):
L = [1, 3, 5, 7, 9]
return fn(L)
print(myinput(max)) # 9
print(myinput(min)) # 1
print(myinput(sum)) # 25
函数可以作为另一个函数的返回值
示例见:
function_as_return_value.py
1 # function_as_return_value.py 2 3 def get_function(): 4 s = input("请输入您要做的操作: ") 5 if s == '求最大': 6 return max 7 elif s == '求最小': 8 return min 9 elif s == '求和': 10 return sum 11 12 L = [2, 4, 6, 8, 10] 13 f = get_function() # ??? f绑定什么? 14 print("f绑定:", f) 15 print(f(L)) 16 17 18 19 20 21 22 23 24 25
练习:
写一个计算公式的解释执行器
已知有如下一些函数:
def myadd(x, y):
return x + y
def mysum(x, y):
return x - y
def mymul(x, y):
return x * y
...
定一个带有一个参数的函数 get_func(s):
def get_func(s):
... # 此处自己实现
此函数的在传入字符串"加"或"+" 返回myadd函数;
此函数的在传入字符串"乘"或"*" 返回mysum函数, ...
在主函数中程序如下:
def main():
while True:
s = input("请输入计算公式: ") # 10 加 20
L = s.split() # L = ['10', '加', '20']
a = int(L[0])
b = int(L[2])
fn = get_func(L[1])
print("结果是:", fn(a, b)) # 结果是: 30
1 # 练习: 2 # 写一个计算公式的解释执行器 3 # 已知有如下一些函数: 4 # def myadd(x, y): 5 # return x + y 6 # def mysum(x, y): 7 # return x - y 8 # def mymul(x, y): 9 # return x * y 10 # ... 11 # 定一个带有一个参数的函数 get_func(s): 12 # def get_func(s): 13 # ... # 此处自己实现 14 # 此函数的在传入字符串"加"或"+" 返回myadd函数; 15 # 此函数的在传入字符串"乘"或"*" 返回mysum函数, ... 16 # 在主函数中程序如下: 17 # def main(): 18 # while True: 19 # s = input("请输入计算公式: ") # 10 加 20 20 # L = s.split() # L = ['10', '加', '20'] 21 # a = int(L[0]) 22 # b = int(L[2]) 23 # fn = get_func(L[1]) 24 # print("结果是:", fn(a, b)) # 结果是: 30 25 26 27 28 29 30 def myadd(x, y): 31 return x + y 32 def mysub(x, y): 33 return x - y 34 def mymul(x, y): 35 return x * y 36 37 def get_func(s): 38 if s == '加' or s == '+': 39 return myadd 40 elif s == '减' or s == '-': 41 return mysub 42 elif s in ('乘', '*'): 43 return mymul 44 45 def main(): 46 while True: 47 s = input("请输入计算公式: ") # 10 加 20 48 L = s.split() # L = ['10', '加', '20'] 49 a = int(L[0]) 50 b = int(L[2]) 51 fn = get_func(L[1]) 52 print("结果是:", fn(a, b)) # 结果是: 30 53 54 main()
1 # 练习: 2 # 写一个计算公式的解释执行器 3 # 已知有如下一些函数: 4 # def myadd(x, y): 5 # return x + y 6 # def mysum(x, y): 7 # return x - y 8 # def mymul(x, y): 9 # return x * y 10 # ... 11 # 定一个带有一个参数的函数 get_func(s): 12 # def get_func(s): 13 # ... # 此处自己实现 14 # 此函数的在传入字符串"加"或"+" 返回myadd函数; 15 # 此函数的在传入字符串"乘"或"*" 返回mysum函数, ... 16 # 在主函数中程序如下: 17 # def main(): 18 # while True: 19 # s = input("请输入计算公式: ") # 10 加 20 20 # L = s.split() # L = ['10', '加', '20'] 21 # a = int(L[0]) 22 # b = int(L[2]) 23 # fn = get_func(L[1]) 24 # print("结果是:", fn(a, b)) # 结果是: 30 25 26 27 28 29 30 31 def get_func(s): 32 def myadd(x, y): 33 return x + y 34 35 def mysub(x, y): 36 return x - y 37 38 def mymul(x, y): 39 return x * y 40 41 if s == '加' or s == '+': 42 return myadd 43 elif s == '减' or s == '-': 44 return mysub 45 elif s in ('乘', '*'): 46 return mymul 47 48 def main(): 49 while True: 50 s = input("请输入计算公式: ") # 10 加 20 51 L = s.split() # L = ['10', '加', '20'] 52 a = int(L[0]) 53 b = int(L[2]) 54 fn = get_func(L[1]) 55 print("结果是:", fn(a, b)) # 结果是: 30 56 57 main()
函数的嵌套定义
函数嵌套定义是指一个函数里用def语句来创建其它函数的情况
示例见:
function_embed_def.py
1 # function_embed_def.py 2 3 4 # 此示例示意函数的嵌套定义 5 def fn_outer(): 6 print("fn_outer被调用") 7 # 此处能否创建新的函数并且调用呢? 8 def fn_inner(): 9 print("fn_inner被调用!") 10 fn_inner() # 调用函数内部的fn_inner 11 fn_inner() 12 print("fn_outer调用结束") 13 14 fn_outer() 15 16
python 作用域
作用域也叫名字空间,是访问变量时查找变量名的范围空间
示例:
a = 100
def fx():
a = 10000 # a=10000和a=100是两个不同作用域内的变量
print(a)
fx()
print(a)
python的四个作用域 LEGB
作用域 英文解释 英文简写
局部作用域(函数内) Local(function) L
外部嵌套函数作用域 Enclosing function local E
函数定义所在模块的作用域 Global(module) G
python 内置模块的作用域 Builtin(Python) B
示例见:
namespace.py
1 # namespace.py 2 3 4 # 此示例示意python的作用域 5 v = 100 6 def fun1(): 7 v = 200 8 print('fun1.v=', v) # 200 9 def fun2(): 10 v = 300 11 print('fun2.v=', v) # 300 12 fun2() 13 14 fun1() 15 print("全局的v=", v) # 100 16 17 18
1 # namespace2.py 2 3 4 # 此示例示意python的作用域 5 v = 100 6 def fun1(): 7 # v = 200 8 print('fun1.v=', v) # ??? 9 def fun2(): 10 # v = 300 11 print('fun2.v=', v) # ??? 12 fun2() 13 14 fun1() 15 print("全局的v=", v) # 100 16 17 18
变量名的查找规则:
在访问变量时,先查找本地变量,然后是包裹此函数外部的子数内部的
变量,之后是全局变量,最后是内置变量,即:
L --> E --> G --> B
在默认的情况下,变量名赋值会创建或者改变本地作用域的变量
练习:
执行以下程序,看执行结果是什么?为什么?
L = [1, 2, 3]
v = 100
def f1():
L.append(4)
v = 200
f1()
print(L) # ???
print(v) # ???
def f2():
L += [5]
v += 1
f2() # 此处会怎么样?为什么?
1 # 练习: 2 # 执行以下程序,看执行结果是什么?为什么? 3 # L = [1, 2, 3] 4 # v = 100 5 # def f1(): 6 # L.append(4) 7 # v = 200 8 # f1() 9 # print(L) # ??? 10 # print(v) # ??? 11 12 # def f2(): 13 # L += [5] 14 # v += 1 15 # f2() # 此处会怎么样?为什么? 16 17 18 19 20 L = [1, 2, 3] 21 v = 100 22 def f1(): 23 L.append(4) 24 v = 200 25 f1() 26 print(L) # ??? 27 print(v) # ??? 28 29 def f2(): 30 L.extend([5]) 31 # L += [5] # 出错 32 v += 1 # 出错 33 f2() # 此处会怎么样?为什么? 34 35 print(L) 36 print(v) 37 38
global语句:
作用:
告诉解释执行器, global语句声明的一个或多个变量,这些变量的
作用域为模块级的作用域,也称作全局变量
全局声明(global) 将赋值变量映射到模块文件内部的作用域
语法:
global 变量1, 变量2, ...
示例:
global ga, gb
global gc
示例见:
global.py
1 v = 100 2 def f1(): 3 global v # 全局声明语句 4 v = 200 # 要想让此语句来修改全局变量v怎么办? 5 6 f1() 7 print(v) # 200
1 # 3. 不能先声明局部变量,再用global声明为全局变量,此做法不 2 # 附合规则 3 4 5 v = 100 6 def fx(): 7 v = 200 8 global v 9 v += 300 10 print("v=", v) # ?? 11 fx() 12 print(v) # ????
1 # global变量列表里的变量名不能出现在函数的形参列表里 2 3 4 v = 100 5 def fx(v): 6 print(v) 7 global v # 出错 8 v = 300 9 10 fx(200) 11 print(v)
说明:
1. 全局变量如果要在函数内部被赋值,则必须经过全局声明(否则
会被认为是局部变量)
2. 全局变量在函数内部不经过声明就可以直接访问(变量已经存在
并关联一个对象)
3. 不能先声明局部变量,再用global声明为全局变量,此做法不
附合规则
4. global变量列表里的变量名不能出现在函数的形参列表里
练习:
用全局变量记录一个函数fx调用的次数,部分代码如下:
count = 0
def fx(name):
print("你好", name)
.... # 此处自己实现
fx('小张')
fx('小李')
print("fx函数共被调用", count, '次') # 2
1 # 练习: 2 # 用全局变量记录一个函数fx调用的次数,部分代码如下: 3 # count = 0 4 # def fx(name): 5 # print("你好", name) 6 # .... # 此处自己实现 7 # fx('小张') 8 # fx('小李') 9 # print("fx函数共被调用", count, '次') # 2 10 11 12 count = 0 13 def fx(name): 14 print("你好", name) 15 global count 16 count += 1 17 fx('小张') 18 fx('小李') 19 print("fx函数共被调用", count, '次') # 2 20
nonlocal 语句
作用:
告诉解释器 nonlocal 声明的变量不是局部变量,也不是全局变量
而是外部嵌套函数内的变量
语法:
nonlocal 变量名1, 变量名2, ...
示例见:
nonlocal.py
1 # nonlocal.py 2 3 4 v = 100 5 6 def f1(): 7 v = 200 8 print("f1.v=", v) 9 # 此外嵌入另一个函数 10 def f2(): 11 nonlocal v # 声明v为外部嵌套函数作用域的变量 12 v = 300 13 print("f2.v=", v) 14 f2() 15 print("f1执行后f1.v=", v) 16 17 f1() 18 19
1 # nonlocal.py 2 3 4 # 3. 当有两层或两层以上函数嵌套时,访问nonlocal变量只对最近 5 # 一层变量进行操作 6 7 v = 100 8 9 def f1(): 10 v = 200 11 print("f1.v=", v) 12 # 此外嵌入另一个函数 13 def f2(): 14 v = 300 15 # 再嵌入另一个函数 16 def f3(): 17 nonlocal v 18 v = 400 19 f3() 20 print("f2.v=", v) # 400 21 f2() 22 print("f1执行后f1.v=", v) 23 24 f1() 25 26
说明:
1. nonlocal语句只能在被嵌套函数内部进行使用
2. 对nonlocal变量进行赋值将对外部嵌套函数作用域内的变量
进行操作
3. 当有两层或两层以上函数嵌套时,访问nonlocal变量只对最近
一层变量进行操作
4. nonlocal语句的变量列表里的变量名,不能出现在此函数形参
列表中
问题:
def 语句的作用是创建函数, 同时用变量名绑定这个函数
lambda 表达式(又称匿名函数)
作用:
创建一个匿名函数对象
同def类似,但不提供函数名
语法:
lambda [函数形式列表]: 表达式
示例见:
lambda.py
1 # lambda.py 2 3 4 # def myadd(x, y): 5 # return x + y 6 7 myadd = lambda x, y: x + y 8 9 print("20 + 30 =", myadd(20, 30)) # 50 10 print("1 + 2 =", myadd(1, 2)) # 3 11 12 13
说明:
lambda 表达式创建的函数只能包含一条表达式
lambda 比函数简单且可以随时创建和销毁,有利于减少程序的偶合度
练习:
1. 写一个lambda 表达式
fx = lambda n: ...
此表达式创建的函数判断n这个数的2次方+1 能否被5整除,如果能被整
除返回True,否则返回False
如:
print(fx(3)) # True
print(fx(4)) # False
1 # 练习: 2 # 1. 写一个lambda 表达式 3 # fx = lambda n: ... 4 # 此表达式创建的函数判断n这个数的2次方+1 能否被5整除,如果能被整 5 # 除返回True,否则返回False 6 # 如: 7 # print(fx(3)) # True 8 # print(fx(4)) # False 9 10 11 12 fx = lambda n: (n ** 2 + 1) % 5 == 0 13 14 print(fx(3)) # True 15 print(fx(4)) # False 16 17
2. 写一个lambda 表达式来创建函数,此函数返回两个形参变量的最
大值
def mymax(x, y):
...
mymax = lambda ......
print(mymax(100, 200)) # 200
print(mymax("100", "20")) # 20 <-- 注意这是字符串
看懂下面的程序在做什么?
def fx(f, x, y):
print(f(x, y))
fx((lambda a, b: a + b), 100, 200)
fx((lambda a, b: a * b), 3, 4)
1 # 2. 写一个lambda 表达式来创建函数,此函数返回两个形参变量的最 2 # 大值 3 # def mymax(x, y): 4 # ... 5 # mymax = lambda ...... 6 # print(mymax(100, 200)) # 200 7 # print(mymax("100", "20")) # 20 <-- 注意这是字符串 8 9 10 11 # def mymax(x, y): 12 # if x > y: 13 # return x 14 # return y 15 16 # def mymax(x, y): 17 # return x if x > y else y 18 19 mymax = lambda x, y: x if x > y else y 20 print(mymax(100, 200)) # 200 21 print(mymax("100", "20")) # 20 <-- 注意这是字符串 22 23
eval() 和 exec() 函数
eval(source, globals=None, locals=None) 把一个字符串
source 当成一个表达式来执行,返回表达式执行后的结果
exec(source, globals=None, locals=None) 把一个字符串
source 当成一个"程序"来执行
eval 函数示例见:
eval.py
1 # eval.py 2 3 x = 100 4 y = 200 5 6 s = 'x + y + 1' 7 r = eval(s) 8 print('r=', r) # 301 9 10 # 先创建一个局部作用域的字典 11 local_scope = {'x': 1, 'y': 2} 12 a = eval(s, None, local_scope) 13 print('a=', a) 14 15 # 创建一个全局作用域的字典 16 global_scope = {'x': 10, 'y': 20} 17 b = eval(s, global_scope) 18 print('b=', b) # 31 19 20 c = eval(s, {'x': 10, 'y': 20}, {'x': 1}) 21 print('c=', c) # 22 22 23 24 25 26 27 28 29 30 31 32 33
exec 函数示例见:
1 # exec.py 2 3 s = ''' 4 myadd = lambda x, y: x + y 5 6 print("20 + 30 =", myadd(20, 30)) # 50 7 print("1 + 2 =", myadd(1, 2)) # 3 8 ''' 9 10 exec(s)
1 2 3 def fx(): 4 def fy(): 5 print("hello") 6 return fy 7 8 fn = fx() 9 fn() # ??? 10 11 def fa(): 12 L = [1, 2, 3, 4] 13 return L 14 L2 = fa() 15 print(L2) 16 17
练习:
1. 写一个函数mysum(n) ,此函数用来计算
1 + 2 + 3 + 4 + ... + n 的和
(要求: 不允许调用sum)
如:
print(mysum(100)) # 5050
print(mysum(4)) # 10
1 # 1. 写一个函数mysum(n) ,此函数用来计算 2 # 1 + 2 + 3 + 4 + ... + n 的和 3 # (要求: 不允许调用sum) 4 # 如: 5 # print(mysum(100)) # 5050 6 # print(mysum(4)) # 10 7 8 9 # 1. 写一个函数mysum(n) ,此函数用来计算 10 # 1 + 2 + 3 + 4 + ... + n 的和 11 # (要求: 不允许调用sum) 12 # 如: 13 14 def mysum(n): 15 s = 0 16 for x in range(1, n + 1): 17 s += x 18 return s 19 20 print(mysum(100)) # 5050 21 print(mysum(4)) # 10 22
1 # 1. 写一个函数mysum(n) ,此函数用来计算 2 # 1 + 2 + 3 + 4 + ... + n 的和 3 # (要求: 不允许调用sum) 4 # 如: 5 # print(mysum(100)) # 5050 6 # print(mysum(4)) # 10 7 8 9 # def mysum(n): 10 # s = 0 11 # for x in range(1, n + 1): 12 # s += x 13 # return s 14 15 def mysum(n): 16 return sum(range(1, n + 1)) 17 18 print(mysum(100)) # 5050 19 print(sum(range(1, 101))) 20 print(mysum(4)) # 10 21
2. 写一个函数myfac(n) 来计算n!(n的阶乘)
n! = 1*2*3*4*....*n
如:
print(myfac(5)) # 120
1 # 2. 写一个函数myfac(n) 来计算n!(n的阶乘) 2 # n! = 1*2*3*4*....*n 3 # 如: 4 # print(myfac(5)) # 120 5 6 def myfac(n): 7 s = 1 8 for x in range(1, n + 1): 9 s *= x 10 return s 11 12 print(myfac(5)) # 120 13 print(myfac(3)) # 6 14 15
3. 写一个函数计算:
1 + 2**2 + 3**3 + ... + n ** n的和
(n给个小点的数来进行测试)
1 # 3. 写一个函数计算: 2 # 1 + 2**2 + 3**3 + ... + n ** n的和 3 # (n给个小点的数来进行测试) 4 5 # 方法1 6 # def mysum(n): 7 # s = 0 8 # for x in range(1, n + 1): 9 # s += x ** x 10 # return s 11 12 # 方法2 13 # def mysum(n): 14 # s = sum([x ** x for x in range(1, n + 1)]) 15 # return s 16 17 # 方法3 18 def mysum(n): 19 return sum(map(lambda x: x**x, range(1, n+1))) 20 21 print(mysum(3)) # 32 22 23
4. 实现带界面的学生信息管理系统
操作界面如下:
+--------------------------+
| 1) 添加学生信息 |
| 2) 显示学生信息 |
| 3) 删除学生信息 |
| 4) 修改学生成绩 |
| q) 退出 |
+--------------------------+
学生信息包括: 姓名,年龄,成绩(与之前相同), 每个功能写一个
函数与之相对应
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 def delete_student(L): 36 name = input("请输入要删除学生的姓名: ") 37 i = 0 # i 代表列表的索引 38 while i < len(L): 39 d = L[i] # d绑定字典 40 if d['name'] == name: 41 del L[i] 42 print("删除", name, "成功!") 43 break 44 else: 45 print("删除失败!") 46 47 def modify_student_score(L): 48 pass 49 50 def show_menu(): 51 '''显示菜单''' 52 print("+--------------------------+") 53 print("| 1) 添加学生信息 |") 54 print("| 2) 显示学生信息 |") 55 print("| 3) 删除学生信息 |") 56 print("| 4) 修改学生成绩 |") 57 print("| q) 退出 |") 58 print("+--------------------------+") 59 60 def main(): 61 infos = [] # 此列表用于保存学生数据 62 while True: 63 show_menu() 64 s = input("请选择: ") 65 if s == '1': 66 infos += input_student() 67 elif s == '2': 68 output_student(infos) 69 elif s == '3': 70 delete_student(infos) 71 elif s == '4': 72 modify_student_score(infos) 73 elif s == 'q': 74 break 75 76 main() 77