'''
匿名函数就是没有名字的函数,需要使用关键字lambda
匿名函数的语法结构:
变量名 = lambda 参数:返回值
参数可以有多个,中间用逗号隔开
匿名函数不管有多复杂的逻辑,也只能写一行 且逻辑执行结束后的内容就是返回值
返回值和正常的函数一样可以是任意数据类型
应用场景
lambda x,y:x+y
匿名函数一般不单独使用,需要配合其他函数一起用,主要用于减少代码
'''
'''正常方式'''
def index(x):
return x**2
res = index(2)
print(res)
'''匿名函数'''
#单参数
res = lambda x:x**2
print(res(2))
#多参数
res = lambda x,y:x+y
print(res(4,5))
#可不赋值
print((lambda a:a+1)(3))
内置函数配合匿名函数使用
1.map()映射
'''# map也像for循环一样把每一个数据值映射出来交给下面的函数名'''
已知现在有一个列表,需要给列表中每个元素开方
ll = [1,2,3,4,5,6]
'''正常方式'''
# 定义一个空列表
num_list = []
for i in ll:
num_list.append(i ** 2)
print(num_list)
'''函数'''
def index(x):
return x **2
res = map(index, ll)
print(res) #
print(list(res)) # 需要转换成对应数据类型
'''匿名函数'''
res = map(lambda x: x ** 2, ll)
print(list(res)) # 需要转换成对应的数据类型
'''
底层也是for循环 循环出每一个数据值,把数据值交给函数去处理,
就会返回数据值,依次顺序循环 这就是映射
'''
2.zip()拉链
#已知现在有两个列表我们需要给他们依次排列
name_list = ['name','age','gender']
zhi_list = ['chen',18,'male']
'''正常方式'''
# 定义一个空列表
new_list = []
for i in range(len(name_list)):
new_list.append((name_list[i],zhi_list[i]))
print(new_list)
'''匿名函数'''
res = zip(name_list,zhi_list)
print(res) #
print(list(res))
'''
注意zip只会连接相同的两个列表 如果列表数据值有多有少的,
那么只会对应着连接最少数据值的,多的列表的多的数据值会被忽略
并且可以多个列表来连接,但是还是一样只能连接多个列表中数据值最少的个数值部分
'''
3.max()最大值 min()最小值
max/min 是不允许跨数据类型比较
# 返回列表中最大值和最小值
ll = [1, 2, 3, 4, 45, 5, 63, 34, 234, 232, 23]
'''正常方式'''
# 通过排序来直接获取最大值/最小值
ll.sort() # 默认从小到大顺序
print(ll)
print(ll[-1])
ll.sort(reverse=True) #倒序
print(ll)
print(ll[-1])
'''max、min方式'''
res = max(ll)
print(res)
res1 = min(ll)
print(res1)
'''
注意:
max、min取字典的时候是默认取的是key值
也是按照key值来比较的
'''
new_dict = {'name': 'chen', 'age': "18", 'gender': 'male'}
res = max(new_dict)
print(res) # name 返回的是key值,并且是按照ASCII编码来比较的
res1 = min(new_dict)
print(res1) # age
'''函数'''
def index(x):
return new_dict[x]
res = max(new_dict,key=index) # 这样就是取的value值
print(res)
res = min(new_dict,key=index) # 这样就是取的value值
print(res)
'''匿名函数'''
res = max(new_dict, key=lambda x:new_dict[x])
print(res)
res = min(new_dict, key=lambda x:new_dict[x])
print(res)
4.filter()过滤
#列表中里面有很多数据值,我们需要移除44
ll = [11,22,33,44,55,66,77]
'''正常方式'''
new_list = []
for i in ll:
if i == 44:
pass
else:
new_list.append(i)
print(new_list)
'''函数'''
def index(x):
return x != 44
res = filter(index, ll) # 内部也是for循环
print(list(res))
'''匿名函数'''
res = filter(lambda x : x!=44 , ll) # 内部也是for循环
print(list(res))
迭代如何理解
'''
迭代就是更新换代 每次迭代都需要基于上一次的成果更新
指存储了元素的一个容器对象 且容器中的元素可以通过'__iter__'方法或'__next__'方法访问
并不是指某种具体的数据类型
'''
代码演示
不属于迭代的:
while True:print('hello world') #无限循环,值没有发生改变
属于迭代:
n = 0
while n < 10:
print(n)
n += 1 # 在循环值在上一次的基础上发生了改变
如何判断可迭代对象
内置有__iter__方法的都叫做可迭代对象
1.内置:通过句点符(键盘上的点号)能够直接点出来的东西就都是内置
2.__xxx__ :针对双下划线开头双下划线结尾的方法 统一读作双下xxx
可迭代对象有:
字符串、列表、字典、元组、集合、文件对象(本身就是迭代器对象)
不是可迭代对象:
整型、浮点型、布尔值、函数名
可迭代对象都能够支持for循环取值
'''可迭代对象调用__iter__方法之后就是迭代器对象了'''
print(l.__iter__()) #
print(iter(l))
def iter(l):
return l.__iter__()
res = iter(l)
print(res)
'''
__iter__开头的方法都有一个与之对应的简写:iter(l)方法名()
'''
'''
1.迭代器对象:
是由可迭代对象调用__iter__方法产生的
迭代器对象判断的本质是看是否内置有__iter__和__next__
2.迭代器对象的作用:
提供了一种不依赖于索引取值的方式
正因为有迭代器的存在 我们的字典 集合才能够呗for循环
3.注意事项:
可迭代对象调用__iter__会成为迭代器对象
迭代器对象如果还调用__iter__不会有任何变化 还是迭代器对象本身
print(res.__iter)
'''
迭代器对象实操
rel = 'hello' # 可迭代对象
res = rel.__iter__() # 迭代器对象
print(res.__next__(),end=' ') # 迭代器取值 for循环本质
print(res.__next__(),end=' ')
print(res.__next__(),end=' ')
print(res.__next__(),end=' ')
print(res.__next__(),end=' ')
print(res.__next__(),end=' ') # 超出索引范围报错: StopIteration
'''一旦__next__取不到值 就会直接报错'''
ll = [11,22,33,44,55,66,77]
# 在不使用for循环的前提下 一次打印出列表中的所有值
res = ll.__iter__() # 转换成迭代器对象
count = 0 # 定义一个计数器
while count < len(ll): # 使用while循环
print(res.__next__(), end=' ')
count += 1
# result 11 22 33 44 55 66 77
'''
针对双下的方法:
res = l.__iter__() # 可以简写iter(l)
res.__next__() #可以简写next(res)
'''
'''
迭代器总结:
迭代取值是一种不依赖与索引(下标)取值的方式
但是它不能重复取值,只能从左往右固定取值
索引取值:
它能够重复取值(通过固定索引一直取)
它需要是容器类型
'''
'''易错题,判断'''
l = [1,2,3,4]
print(l.__iter__().__next__()) # 1
print(l.__iter__().__next__()) # 1
print(l.__iter__().__next__()) # 1
print(l.__iter__().__next__()) # 1
'''上面这种相当于每次都重新计算了'''
res = l.__iter__()
print(res.__next__()) # 1
print(res.__next__()) # 2
print(res.__next__()) # 3
print(res.__next__()) # 4
'''上面这种就还是在第一个基础上继续next'''
'''for循环原理'''
l = [1,2,3,4,5,6]
# 不使用for循环,循环打印出列表中每一个值
count = 0
while True:
print(l[count],end=' ')
count += 1
res = l.__iter__()
while True:
print(res.__next__())
'''
会报错,但是能完整的打印出来了,因为while循环是不停的循环,所以__next__会一直往下,
一旦超出了该列表能打印的限度就会报错
'''
'''为什么for循环不会报错呢'''
# 使用for循环打印列表中每一个值
for i in l:
print(i,end=' ')
# 内部本质是这样的,其实就是while循环加上迭代器对象在加上异常捕捉,所以就不会报错
res =l.__iter__()
while True:
try:
print(res.__next__())
except:
break
'''
语法结构:
for 变量名 in 可迭代对象:
for循环体代码
for循环内部的原理:
1.for会自动将in后面的数据值调用__iter__()使之变成迭代器对象
2.之后每次while循环调用__next__()取值
3.最后没有值__next__()会报错 for循环会自动捕获并处理
'''
异常就是我们在程序代码运行中发现错误导致运行不了报错。也就是行业俗称叫bug
1. Traceback:追踪信息,异常发生的位置
File "D:/Python27/day17/05 for循环内部原理.py", line 21, in <module>
# 有时候错误发生的信息可能会有很多行,你就找最后一行,然后点击可以跳转到错误发生的位置
2. XXXError: 异常发生的类型
NameError KeyError ...
3. 错误发生的详细信息(最重要的:一般情况从这里就可以知道错位发生的原因)
name 'a' is not defined
异常的类型
1.NameError 未声明/初始化对象(没有属性)
2.IndexError 序列中没有此索引(index)
3.KeyError 映射中没有这个键
4.SyntaxError Python 语法错误
5.TypeError 对类型无效的操作
6.ValueError 传入无效的参数
7.ImportError 导入模块/对象失败
1. 语法错误
是代码运行过程中一开始就不允许的,只要语法错误,代码一定是不能够运行的
通过代码提示就知道语法错误的原因
2. 逻辑错误
在编码过程中,逻辑错误是允许出现的
但是我们应该尽量避免逻辑错误出现的可能性
'''异常是如何捕获的'''
try:
l = [1,2,3]
print(l[3])
except NameError as e: # 未声明/初始化对象(没有属性)
print(e)
except KeyError as e: # 映射中没有这个键
print(e)
except IndexError as e: # 序列中没有此索引(index)
print(e)
except ZeroDivisionError as e: # 除值为零
print(e)
except Exception as e: # 常规错误的基类
print(e)
else:
# 当被检测的代码没有异常的时候会走这个语法
print('这里是else语法')
finally:
#不管被监测的代码是否异常都会走
print('这里是finally语法')
print(123)
'''
只能当你的被监测的代码可能出现,但是你又不想它报错,这个时候就可以使用异常捕获是最合适的
异常捕获的代码经量少写
'''
ll = [1,2,3,4,5,6]
res = ll.__iter__()
while True:
try:
print(res.__next__())
except Exception: # 常规错误的汇总
break