##python基础编程
day10 回顾
函数名是变量
函数可以作为另一个函数的参数传入
fx(max)
函数可以作为另一个函数的返回值:
def fy():
return max
函数的嵌套定义
def fx():
def fy():
print("fy")
fy() # 调用内嵌函数
return fy # 返回内嵌函数引用关系
f1 = fx # f1 绑定 fx
f2 = fx() # f2 绑定fx调用时内部创建的fy
python 的四个作用域
局部作用域local
外部嵌套函数作用域 enclosing function local
模块的作用域(全局) global(module)
内建模块的作用域
访问变量名时查找变量名字所在的空间
声明语句
global 语句
nonlocal 语句
lambda 表达式
lambda x, y, z : x + y + z
新的一天
###eval 函数 和 exec 函数
eval 函数:
格式:
eval(source, globals=None, locals=None) 把一个字符串
source 当成一个表达式来执行,返回表达式执行的结果
参数:
source 符合python语法规则的字符串
globals 声明全局作用域的字典
locals 声明局部作用域的字典
示例见:
eval.py
```
s = '1 + 2 * 3'
v = eval(s) # 解释执行s绑定的内容,并返回结果
print('v=', v) # 7
```
eval2.py
```
s = 'x + y'
global_dict = {'x': 1, 'y': 2}
v = eval(s, global_dict)
print('v=', v)
local_dict = {'x':100, 'y': 200}
v2 = eval(s, global_dict, local_dict)
print('v2=', v2) # 300
v3 = eval(s, {'x': 1, 'y': 2}, {'x':100})
print('v3=', v3) # v3 = 102
```
-exec 函数
作用:
把一个字符串当成程序来执行
格式:
exec(source, globals=None, locals=None)
参数:
同eval参数
示例见
s = '''
fx = lambda n: (n ** 2 + 1) % 5 == 0
print(fx(3)) # True
print(fx(4)) # False
'''
exec(s)
函数式编程 functional programming
函数式编程是指用一系列函数解决问题
函数式编程的优点:
用每一个函数完成细小的功能,一系列函数的任意组合可以解决
大问题
函数仅接受输入并生成输出,不包含任何能够影响输出的内部状态
函数的可重入性:
当一个函数不访问除局部变量以外的变量时,这样的函数称为可重入
函数
可重入函数的特点:
输入一定.结果必须一定
示例:
# 可重入函数:
def myadd1(x, y):
return x + y
# 不可重入函数
s = 0
def myadd2(x, y):
global s
s += x + y
return s
高阶函数 High Order Function
什么是高阶函数
满足下列条件中一个的函数即为高阶函数
1. 函数接受一个或多个函数作为参数传入
2. 函数返回一个函数
内建高阶函数:
map, filter, sorted
map函数:
格式:
map(func, iterable1, iterable2, ...)
作用:
返回一个可迭代对象,此可迭代对象的数据来自于iterable1,
iterable2, 数据被func处理后,得到处理后的结果
说明:
当最短的一个可迭代对象不再提供数据时,迭代结束
参数:
func 处理函数
iterable1 和 iterable2, 可迭代对象,可以有一个或多个
示例见:
map.py
```
def power2(x):
print("power2传入:", x, '返回:', x**2)
return x ** 2
# 生成一个可迭代对象,此可迭代对象可以生成1~9的平方
for x in map(power2, range(1, 10)): # 可迭代对象:
print(x) # 1, 4, 9, 16, ....
```
map2.py
练习:
1. 求 1**2 + 2**2 + 3**2 + .... + 9**2 的和
```
def pow(x):
return x**2
for i in map(pow,range(1,10)):
print(i)
```
2. 求 1**3 + 2**3 + 3**3 + .... + 9**3 的和
```
def pow(x):
return x**3
for i in map(pow,range(1,10)):
print(i)
```
3. 求 1**9 + 2**8 + 3**7 + .... + 9**1 的和
```
def pow(x,y):
return x**y
for i in map(pow,range(1,10),range(9:0:-1)):
print(i)
```
filter 函数
格式:
filter(func, iterable)
作用:
筛选可迭代对象iterable中的数据,返回一个可迭代对象,此可
迭代对象只提供iterable提供的数据中满足条件的数据.
参数说明:
func 含有一个形参的处理函数.此参数传入值为iterable中
提供的数据,此函数func将对iterable中的每个元素进
行求布尔值,返回True则保留,返回False,则丢弃此数据
iterable 提供数据的可迭代对象
示例见:
def is_odd(x):
'''判断x是否是奇数,如果是奇数返回True,否则返回False'''
return x % 2 == 1
# 生成从 0 到 20 以内的奇数:
for x in filter(is_odd, range(0, 20)):
print(x)
# 创建一个列表,此列表内的数据为1~100之间的奇数
L = [x for x in filter(is_odd, range(1, 100))]
print(L)
练习:
1. 用filter函数生成 1~20之间的全部偶数(不包含20):
将这些数字存于列表中,再打印这个列表
```
def is_odd(x):
return x%2==0
L = [i for i in filter(is_odd,range(1,20))]
print(L)
```
2. 用filter函数将1~100之间所有的素数放到L列表中,再印出
这个列表.
```
def is_prime(x):
if x<2:
return False
for i in range(2,x)L
if x%i ==0:
return False
return True
L = list(filter(is_prime,range(100)))
print(L)
```
sorted 函数
作用:
将原可迭代对象的数据进行排序,生成排序后的列表
格式:
sorted(iterable, key=None, reverse=False)
参数说明:
iterable 可迭代对象
key 函数是用来提供一个值,这个值将作为排序的依据
reverse 标志是否设置为降序排序
示例:
L = [5, -2, -4, 0, 3, 1]
L2 = sorted(L) # L2 = [-4, -2, 0, 1, 3, 5]
L3 = sorted(L, reverse=False) # [-4, -2, 0, 1, 3, 5]
L4 = sorted(L, key=abs) # L4 = [0, 1, -2, 3, -4, 5]
L5 = sorted(L, key=abs, reverse=True)
# L5 = [5, -4, 3, -2, 1, 0]
names = ['Tom', 'Jerry', 'Spike', 'Tyke']
L6 = sorted(names) # ['Jerry', 'Spike', 'Tom', 'Tyke']
L7 = sorted(names, key=len)
# 依据字符串长度 ['Tom', 'Tyke', 'Jerry', 'Spike']
练习:
names = ['Tom', 'Jerry', 'Spike', 'Tyke']
排序的依据是最后一个字符的编码值大小,如果最后一个,依次
sorted(names,)
向前对比,即依据为:
```
def getkey(x):
r = x[::-1]
return r
result = sorted(names,key=getkey)
```
'moT' 'yrreJ' 'ekipS' 'ekyT'
排序后结果为:
['Spike', 'Tyke', 'Tom', 'Jerry']
###递归函数 recursion
函数直接或间接的调用自身
故事:
从前有座山,山上有座庙,庙里有个老和尚讲故事:
从前有座山,山上有座庙,庙里有个老和尚讲故事:
...
程序描述:
def story():
print('从前有座山,山上有座庙,庙里有个老和尚讲故事:')
story()
story()
print("程序结束")
- 递归示意:
# 函数直接的调用自身
def fa():
fa()
fa()
# 函数间接的调用自身
def fa():
fb()
def fb():
fa()
fa()
递归说明:
递归一定要控制递归的层数,当符合某一条件时要终止递归调用
几乎所有的递归都能用while循环来代替
递归的优缺点:
优点:
递归可以把问题简单化,让思路更为清晰,代码更简洁
缺点:
递归因系统环境影响大,当递归深度太大时,可能会得到不可预知
的结果
递归函数的调用过程分为两个阶段:
递推阶段:
从原问题出发,按递归公式递推从未知到已知,最终达到递归终止条件
回归阶段:
按递归终止条件,逆向代入递归公式,回归原问题求解
限制递归层数示例见:
```
def fx(n):
print("递归进入第", n, '层')
if n == 3:
return
fx(n + 1)
print("递归退出第", n, '层')
fx(1)
print("程序结束")
```
递归的示例见:
```
def myfac(n):
if n == 0:
return 1
r = n * myfac(n-1)
return r
print(myfac(0)) # 1
print(myfac(5)) # 120
print(myfac(6)) # 720
```
练习:
用递归的方式求和
def mysum_recursion(n):
...
print(mysum_recursion(100)) # 5050
练习:
已知有五位朋友在一起
第五位朋友比第四位大2岁
第四位朋友比第三位大2岁
第三位朋友比第二位大2岁
第二位朋友比第一位大2岁
第一位朋友说他10岁
编写函数,算出第五位朋友几岁,第三位朋友几岁?
```
def get_age(n):
if n==1:
return 10
return get_age(n-1) + 2
```
闭包 closure
闭包是指引用了此函数外部嵌套函数的变量的函数
闭包必须满足三个条件:
1. 必须有一个内嵌函数
2. 内嵌函数必须引用外部函数中的变量
3. 外部函数返回值必须是内嵌函数
思考: 全局变量和局部变量的区别?
全局变量
一直存在,谁都可以访问和修改
局部变量:
只是在调用时存在,只能在函数内部进行访问和修改
示例见:
closure.py
money = 1000 # 家长给孩子压岁钱1000元
def child_buy(obj, m):
'''m 代表物品 obj 的价格'''
global money
if m < money:
money -= m
print('买', obj,'花了', m, '元剩余', money, '元')
else:
print('钱不够,买', obj, '失败')
child_buy('变形金刚', 200)
money = 0
child_buy('漫画三国', 100)
child_buy('手机', 1300)
```
closure2.py
def child_buy(obj, m):
'''m 代表物品 obj 的价格'''
money = 1000 # 家长给孩子压岁钱1000元
if m < money:
money -= m
print('买', obj,'花了', m, '元剩余', money, '元')
else:
print('钱不够,买', obj, '失败')
child_buy('变形金刚', 200)
money = 0
child_buy('漫画三国', 100)
child_buy('手机', 1300)
```
closure3.py
def give_yashiqian(m):
money = m
def child_buy(obj, m):
'''m 代表物品 obj 的价格'''
nonlocal money
if m < money:
money -= m
print('买', obj,'花了', m, '元剩余', money, '元')
else:
print('钱不够,买', obj, '失败')
return child_buy
cb = give_yashiqian(1000) # 家长给孩子压岁钱1000元
cb('变形金刚', 200)
money = 0
cb('漫画三国', 100)
cb('手机', 1300)
```
说明:
闭包内绑定的外部嵌套函数的变量会延迟销毁,即:当闭包(内嵌
函数)被释放时,外部嵌套函数的变量才会被释放
练习:
1. 写程序算出1~20的阶乘的和
即:
```python
def is_jie(n):
if n==1:
return 1
return n*is_jie(n-1)
sum(map(is_jie,range(1,21)))
```
1! + 2! + 3! + ... + 19! + 20!
2. 已知有列表:
L = [[3, 5, 8], 10, [[13, 14], 15, 18], 20]
1) 写一个函数print_list(lst) 打印出所有的数据
print_list(L) # 打印 3 5 8 10 13 14 ...
注: 不要求打印在一行内
```
L = [[3, 5, 8], 10, [[13, 14], 15, 18], 20]
def print_list(lst):
for x in lst:
if type(x) is int: # 如果整数,则打印
print(x)
else: # 如果是列表,则用prine_list来打印
print_list(x) # 递归调用
```
2) 写一个函数sum_list(lst) 返回这个列表中所有数字的和
print(sum_list(L)) # 106
注:简单不做
type(x) 可以返回一个对象的类型
如:
>>> type(10) is int # True
>>> type([3, 5, 8]) is list # True
3. 改写之前的学生信息管理程序,要求添加四个功能:
| 5) 按学生成绩高-低显示学生信息 |
| 6) 按学生成绩低-高显示学生信息 |
| 7) 按学生年龄高-低显示学生信息 |
| 8) 按学生年龄低-高显示学生信息 |
```
def input_student():
'''此函数录入学生信息,最后返回学生信息的字典的列表'''
L = [] # 先创建一个列表容器,准备存放字典
while True:
n = input("请输入姓名: ")
if not n: # 如果n绑定空字符串,则退出录入信息
break
a = int(input("请输入年龄: "))
s = int(input("请输入成绩: "))
d = {} # 创建字典,准备存放学生信息
d['name'] = n
d['age'] = a
d['score'] = s
L.append(d)
return L
def output_student(L):
'''以表格形式打印学生信息'''
print("+--------------+----------+----------+")
print("| 姓 名 | 年 龄 | 成 绩 |")
print("+--------------+----------+----------+")
for d in L:
sn = d['name'] # sn绑定姓名的字符串
sa = str(d['age']) # sa 绑定年龄的字符串
ss = str(d['score']) # ss 绑定成绩的字符串
s = "|%s|%s|%s|" % (sn.center(14),
sa.center(10),
ss.center(10))
print(s)
print("+--------------+----------+----------+")
def delete_student(L):
name = input("请输入删除学生的姓名: ")
for i in range(len(L)): # i代表索引
d = L[i]
if d['name'] == name: # 找到了
del L[i]
print("成功删除了: ", name)
return
print("删除失败!")
def modify_student_score(L):
name = input("请输入修改成绩的学生姓名: ")
for i in range(len(L)):
d = L[i]
if d['name'] == name:
score = int(input("请输入要修改学生的成绩: "))
d['score'] = score
print("修改成绩成功!")
return
print("这个学生不存在,修改成绩失败!")
def print_student_by_score_asc(L):
def get_score(d):
return d['score']
L2 = sorted(L, key=get_score)
output_student(L2)
def print_student_by_score_desc(L):
def get_score(d):
return d['score']
L2 = sorted(L, key=get_score, reverse=True)
output_student(L2)
def print_student_by_age_asc(L):
L2 = sorted(L, key=lambda d: d['age'])
output_student(L2)
def print_student_by_age_desc(L):
L2 = sorted(L, key=lambda d: d['age'], reverse=True)
output_student(L2)
def show_menu():
print('+--------------------------------+')
print('| 1) 添加学生信息 |')
print('| 2) 显示学生信息 |')
print('| 3) 删除学生信息 |')
print('| 4) 修改学生成绩 |')
print('| 5) 按学生成绩高-低显示学生信息 |')
print('| 6) 按学生成绩低-高显示学生信息 |')
print('| 7) 按学生年龄高-低显示学生信息 |')
print('| 8) 按学生年龄低-高显示学生信息 |')
print('| q) 退出 |')
print('+--------------------------------+')
def main():
infos = [] # 此列表用来保存学生信息的数据
while True:
show_menu()
s = input("请选择: ")
if s == '1':
infos += input_student()
elif s == '2':
output_student(infos)
elif s == '3':
delete_student(infos) # 删除学生
elif s == '4':
modify_student_score(infos) # 修改学生成绩
elif s == '5':
print_student_by_score_desc(infos) # desc降序
elif s == '6':
print_student_by_score_asc(infos) # asc升序
elif s == '7':
print_student_by_age_desc(infos)
elif s == '8':
print_student_by_age_asc(infos)
elif s == 'q':
break
main()
```