(本文仅用于记录)
01. 昨日内容回顾
02. 作业讲解
03. 函数名的使用
04. 闭包
05. 迭代器
06. 递归(掌握不熟练,需大量练习)
07. 今日总结
01. 昨日内容回顾
动态参数: 动态位置参数 --------->动态关键字参数
参数排序:位置参数--------->关键字参数---------->动态位置参数------------>默认参数------------>动态关键字参数(注意每个函数的区别)
打散和聚合.
函数注释的查询(函数名.__doc__),作用(排bug,交接工作),提升效率
名称空间: 内置空间--------->全局空间--------->局部空间. (加载顺序) 取值顺序相反.
作用域:全局作用域 和 局部作用域.
函数的嵌套:3种. 第一种嵌套(俄罗斯套娃) 第二种(交叉调用),多种函数相互嵌套 第三种,多个俄罗斯套娃
要重温global和nonlocal的含义和用法. 注意都是在调用之前声明.
02. 作业讲解
demo1: # 1. day10作业及默写 # 1.继续整理函数相关知识点,写博客。 # pass # 2.写函数,接收n个数字,求这些参数数字的和。(动态传参) # def do(*args): # s = 0 # for i in args : # s += int(i) # print(s) # do(1,2,3,324,546) # 3.读代码,回答:代码中,打印出来的值a,b,c分别是什么?为什么? # a = 10 # b = 20 # def test5(a, b): # print(a, b) # c = test5(b, a) # print(c) # a是20,b是10,c是none. 因为在c=test5(b,a)处,b=20,a=10,放在test5中则是a对应20,b对应10,因此输出20,10, # print(c)是返回值,未对return作要求,所以为none. # 4.读代码,回答:代码中,打印出来的值a,b,c分别是什么?为什么? # a = 10 # b = 20 # def test5(a, b): # a = 3 # b = 5 # print(a, b) # c = test5(b, a) # print(c) # 3,5,none. a,b进入函数之后,被里面的a,b覆盖,所以输出分别为3,5. c的话是因为return返回none. # 5.传入函数中多个列表和字典,如何将每个列表的每个元素依次添加到函数的动态参数args里面? # 如何将每个字典的所有键值对依次添加到kwargs里面? # def do(*args, **kwargs): # lis = [] # dic = {} # for i in args: # if type(i) is list: # lis.extend(i) # args = lis # else: # dic.update(i) # kwargs = dic # print(args, kwargs) # do([1, 2, 3], [2, 3, 4], [3, 4, 5], {'a': 1, 'b': 2}, {'c': 3, 'd': 4}) # 6.下面代码成立么?如果不成立为什么报错?怎么解决? # 6.1 # a = 2 # def wrapper(): # print(a) # wrapper() # 答: # 成立. # 6.2 # a = 2 # def wrapper(): # a += 1 # print(a) # wrapper() # 答: # 错误. 因为局部变量没有a. 要到全局变量寻找,加个global a即可. # demo: # a = 2 # def wrapper(): # global a # a += 1 # print(a) # wrapper() # 6.3 # def wrapper(): # a = 1 # def inner(): # print(a) # inner() # wrapper() # 答: # 成立. # 6.4 # def wrapper(): # a = 1 # def inner(): # a += 1 # print(a) # inner() # wrapper() # 答: # 错误.因为未定义a.应使用nonlocal a进行声明. # demo: # def wrapper(): # a = 1 # def inner(): # nonlocal a # a += 1 # print(a) # inner() # wrapper() # 7.写函数,接收两个数字参数,将较小的数字返回. # def compare(a, b): # c = a if a < b else b # print(c) # compare(1, 2) #法二:(老师写) # def lowest(argv1,argv2): # return argv1 if argv2 else argv2 #经典的三元运算符 # 8.写函数,接收一个参数(此参数类型必须是可迭代对象),将可迭代对象的每个元素以’_’相连接, # 形成新的字符串,并返回. # 例如 传入的可迭代对象为[1,'老男孩','武sir']返回的结果为’1_老男孩_武sir’ # def do(a): # l = [] # a = list(a) # for i in a: # i = str(i) # l.append(i) # b = '_'.join(l) # print(b) # do([1,'老男孩','武sir']) # 9.有如下函数: # def wrapper(): # def inner(): # print(666) # wrapper() # # 你可以任意添加代码,执行inner函数. # def wrapper(): # def inner(): # print(666) # inner() # wrapper() # 明日默写内容: # 1.形参的接收顺序。 # 位置参数 > 关键字参数 > 动态形参 > 默认参数 > 动态关键字参数 # 2.什么是全局名称空间,什么是局部名称空间,什么是内置名称空间。 # 一个py文件就是一个全局名称空间. # 一个函数内部就是局部名称空间. # 在新建一个py文件是总发现print等内置函数可以使用,它们存放的地方就是内置名称空间. # 3.名称空间的加载顺序,取值顺序。 # 加载顺序: # 1.内置名称空间. # 2.全局名称空间. # 3.局部名称空间. #取值顺序: # 反着来. # 1.局部名称空间. # 2.全局名称空间. # 3.内置名称空间. # 4.解释一下什么是global,什么是nonlocal。 # global:在局部修改全局变量,如果没有就创建一个新的. 他是寻求全局变量的,而不是找上一层的区间空间的变量. #nonlocal:在局部空间内,修改离自己最近的变量(注意从上不从下,如果nonlocal下面有的话只会报错), #如果上一层没有就继续寻找,直到寻找到局部变量的第一层,局部变量没有可以修改的就报错.
03. 函数名的使用
函数名可以当做返回值被返回;
函数名可以当做值赋值给变量;
函数名可以当做容器里的元素;
函数名可以当做参数传递.
demo1:
def f(): def a(): def b(): def c(): return '哈撒给!' return c() return b() return a() print(f())
04. 闭包
1. 一个嵌套函数
2. 在嵌套函数的内部函数使用外部(非全局的变量)
满足上述两种情况就是闭包.
注意,验证时候是 函数名.__closure__ 不是none的就是闭包了.
闭包用在什么地方?
如果有被污染或者不安全的现象,就用闭包.
demo2: money = 10 def wrapper(): money = 10 def inner(num): nonlocal money money += num print(money) return inner wrapper()(100)
注意,Python中闭包会进行内存驻留,普通函数使用完就会销毁了.
全局存放会有污染和不安全的现象.
闭包有个弊端:会出现内存泄漏.
05. 迭代器
可迭代对象:
可以被for循环的就是可循环对象. eg : str , tuple ,dict ,set ,list.
迭代器的特性:
1.惰性机制;(执行一次输出一次,节约内存)
2.不可回卷;
3.一次性.
方法有:__iter__,__next__
其中iter是创建一个迭代器, next是输出一次迭代器.(在创建的时候可以写iter(li))
06. 递归
1.自己调用自己.
2.有明确的结束条件.
递归有深度.
官方的最大深度是1000.
实际上基本是998左右.
import sys
sys.setrecursionlimit(10000)
效率最高的是尾递归. 其效率和for循环一样.
递归的应用场景:
在不明确循环次数时候,可以使用.
for循环的本质:
用while循环出来.
斐波那契数列: def feb(n): if n == 1: return 1 if n == 2: return 2 return feb(n-1) + feb(n-2)