01 今日内容大纲
- global nonlocal
- 函数名的运用
- 新特性:格式化输出
- 迭代器:
- 可迭代对象
- 获取对象的方法
- 判断一个对象是否是可迭代对象
- 小结
- 迭代器
- 迭代器的定义
- 判断一个对象是否是迭代器
- 迭代器的取值
- 可迭代对象如何转化成迭代器
- while循环模拟for循环机制
- 小结
- 可迭代对象与迭代器的对比
02 昨日内容回顾以及作业讲解
-
函数的参数:
- 实参角度:位置参数,关键字参数,混合参数。
- 形参角度:位置参数,默认参数,仅限关键字参数,万能参数。
- 形参角度参数顺序:位置参数,*args, 默认参数,仅限关键字参数,**kwargs.
-
*的魔性用法:
- 函数的定义时:代表聚合。
- 函数的调用时:代表打散。
-
python中存在三个空间:
- 内置名称空间:存储的内置函数:print,input.......
- 全局名称空间:py文件,存放的是py文件(除去函数,类内部的)的变量,函数名与函数的内存地址的关系。
- 局部名称空间:存放的函数内部的变量与值的对应关系。
-
加载顺序:内置名称空间,全局名称空间, 局部名称空间(执行函数时)。
-
取值顺序:就近原则。LEGB.
-
局部作用域只能引用全局变量,不能修改。
name = 'alex' def func(): name = name + 'sb'
-
-
作用域:
- 全局作用域:内置名称空间 + 全局名称空间。
- 局部作用域:局部名称空间。
-
函数的嵌套
-
globals() locals()
03 今日内容
-
global nonlocal
-
补充:
默认参数的陷阱
# 默认参数陷阱 def func(name,sex='男'): print(name) print(sex) func('alex') # alex # 男 # 陷阱只针对于默认参数是可变的数据类型 def func(name,alist=[]): alist.append(name) return alist ret1 = func('alex') print(ret1,id(ret1)) ret2 = func('太白金星') print(ret2,id(ret2)) # 如果你的默认参数指向的是可变的数据类型,无论你调用多少次这个默认参数,都是同一个. def func(a,alist = []): alist.append(a) return alist print(func(10,)) #func(100,)还没执行 print(func(20,[])) print(func(100,)) def func(a,list=[]): list.append(a) return list ret1 = func(10,) ret2 = func(20,[]) ret3 = func(100,) print(ret1) #[10, 100] 函数已经调用 print(ret2) #[20] print(ret3) #[10, 100]
-
局部作用域的坑:
# 局部作用域的坑 count = 1 def func(): count += 1 print(count) func() #在函数中,如果你定义了一个变量,但是在定义这个变量之前对其引用了,那么解释器认为:语法问题. # 你应该在使用之前先定义 count = 1 def func(): print(count) count = 3 func()
global nonlocal:
# global nonlocal # global # 1.在局部作用域声明一个全局变量 name = 'alex' def func(): global name print(name) name = '太白金星' func() print(name) def func(): global name name = '太白金星' print(locals()) #{} print(name) print(globals()) func() print(name) print(globals()) # 2.修改一个全局变量 count = 1 def func(): # print(count) global count count += 1 print(count) func() print(count) # nonlocal # 1.不能操作全局变量 count = 1 def func(): nonlocal count count += 1 func() #报错! # 2.局部作用域:内层函数对外层函数的局部变量进行修改 def wrapper(): count = 1 def inner(): nonlocal count count += 1 print(count) inner() print(count) wrapper()
-
-
函数名的运用:
def func(): print(666) print(func)#<function func at 0x0000028026651EA0> #函数名指向的是函数的内存地址<function func at 0x0000028026651EA0> # 函数名+()就可以执行函数 a = 1 # a() 报错 # func() # a = {'name': 'alex'} # b = {'age' : 18} a = 1 b = 2 print(a + b) print(func,type(func)) # <function func at 0x000001BA864E1D08> <class 'function'> # 2.函数名就是变量 def func(): print(666) print(func) # a = 2 #相当于 # b = a # c = b # print(c) f = func f1 = f f2 = f1 f() func() f1() f2() def func(): print('in func') def func1(): print('in func1') func1 = func func() #in func # 3.函数名可以作为容器类数据类型的元素 def func1(): print('in func1') def func2(): print('in func2') def func3(): print('in func3') l1 = [func1,func2,func3] for i in l1: i() # 4.函数名可以作为函数的参数 def func(a): print(a) print('in func') b = 3 func(b) print(func)#<function func at 0x000001F3E79F1EA0> def func(): print('in func') def func1(x): x() print('in func1') func1(func) # 5.函数名可以作为函数的返回值 def func(): print('in func') def func1(x): print('in func1') return x ret = func1(func)# = func ret()# = func()
-
新特性:格式化输出
# 新特性:格式化输出 name = '太白' age = 18 msg = f'我叫{name},今年{age}' print(msg) # 可以加表达式 dic = {'name':'alex','age':79} msg = f'我叫{dic["name"]},今年{dic["age"]}' print(msg) count = 7 print(f'最终结果为{count**2}') name = 'barry' print(f'我的名字是{name.upper()}') # 结合函数写 def _sum(a,b): return a+b msg = f'最终的结果是{_sum(2,5)}' print(msg) #!,:{}这些标点不能出现在{}里面 # 优点: # 1.结构更加简化 # 2.可以结合表达式和函数进行使用 # 3.效率可以提升很多
优点:
- 结构更加简化
- 可以结合表达式和函数进行使用
- 效率提升很多
-
迭代器:
-
可迭代对象
-
字面意思:对象? python中一切皆对象.一个实实在在存在的值
-
可迭代?:更新迭代,重复的,循环的过程,更新迭代每次都有新内容
-
可以进行循环更新的一个实实在在的值
-
专业角度:可迭代对象?内部含有
'__iter__'
方法的对象,可迭代对象 -
目前学过的可迭代对象? str list tuple dict set range文件句柄
-
获取对象的所有方法并且以字符串的形式表现:dir()
-
判断一个对象是否是可迭代对象:
# 获取一个对象的所有方法:dir() s1 = 'afaasda' l1 = [11,22,33,44,55,66,77,88,99,] print(dir(s1)) print(dir(l1)) print('__iter__'in dir(s1)) print('__iter__'in dir(range(10)))
-
小结:
- 字面意思:可以进行循环更新的一个实实在在值.
- 专业角度:内部含有
'__iter__'
方法的对象,为可迭代对象 - 判断一个对象是不是可迭代对象:
'__iter__'in dir(对象)
- str list tuple dict set range
- 优点:
- 存储数据直接能显示,比较直观.
- 拥有的方法比较多,操作方便
- 缺点:
- 占用内存
- 不能直接通过for 循环,不能直接取值(索引,key除外)(里面做了一步转化,先转化成迭代器,然后再取值)
-
迭代器
-
迭代器的定义
- 字面意思:更新迭代,器:工具:可以更新迭代的工具
- 专业角度:内部含有
'__iter__'
的方法,并且含有'__next__'
方法的对象就是迭代器 - 可以判断是否是迭代器:
'__iter__'
and'__next__'
是否在dir(对象)中
-
判断一个对象是否是迭代器:
with open('文件1.txt',encoding='utf-8',mode='w') as f1:#文件曲柄为迭代器 print(('__iter__'in dir(f1))and('__next__'in dir(f1)))
-
迭代器的取值:
# 可迭代对象可以转化成迭代器 s1 = 'a;akldsjfklsdlk' obj = iter(s1)#s1.__iter__() print(obj) print(next(obj))#print(obj.__next__()) print(next(obj)) print(next(obj)) print(next(obj)) print(next(obj)) print(next(obj)) print(next(obj)) print(next(obj)) # 可迭代对象可以转化成迭代器 s1 = 'a;akldsjfklsdlk' obj = iter(s1)#s1.__iter__() print(obj) print(next(obj))#print(obj.__next__()) print(next(obj)) print(next(obj)) print(next(obj)) print(next(obj)) print(next(obj)) print(next(obj)) print(next(obj))
-
可迭代对象如和转化成迭代器
iter([1,2,3,4,5])
-
while循环模拟for 循环机制
l1 = [11,22,33,44,55,66,77,88,99,1111,1133,15652] # for i in l1: # print(i) # 利用while 循环,模拟for 循环和迭代器对象的取值机制: obj = iter(l1) while 1: try: print(next(obj)) except StopIteration:#报错类型 break
-
小结:
- 字面意思:更新迭代,器:工具:可更新迭代的工具
- 专业角度:内部含有
'__iter__'
方法并含有'__next__'方法的对象就是迭代器
- 优点:
- 节省内存
- 惰性机制,next一次,只取一个值
- 缺点:
- 速度慢
- 不走回头路
-
-
可迭代对象与迭代器的对比:
- 可迭代对象是一个操作方法多,比较直观,存储数据相对少(几百万个对象,8G内存可以承受)的一个数据集.
- 当你侧重于对于数据可以灵活处理,并且内存空间足够将数据集设置为可迭代对象是明确的选择.
- 迭代器,非常节省内存,可以记录取值位置,可以直接通过循环+next方法取值,但不直观,操作方法比较单一的数据集.
- 当你数据量过大,大到足以撑爆内存或者以节省内存为首选因素时,将数据集设置为迭代器是一个不错的选择
-
04 今日总结
- 默认参数的坑,作用域的坑!!!
- 格式化输出
- 函数名的应用
- 可以做赋值运算
- 可以做容器类型的元素
- 可以做函数的参数
- 可以做函数的返回值
- 对比:迭代器是什么?迭代器的优缺点,可迭代对象转化成迭代器,next对迭代器取值
05 明日内容
- 生成器
- 列表推导式