匿名函数,内置函数,闭包

2020-01-16 15:35:26 浏览数 (1)

  1. 内容
    1. 匿名函数:一句话函数,比较简单的函数。 函数名 = lambda 参数 : 返回值
    1. 此函数不是没有名字,他是有名字的,他的名字就是你给其设置的变量,比如func。 func() 函数执行
    2. lambda 是定义匿名函数的关键字,相当于函数的def.
    3. lambda 后面直接加形参,形参加多少都可以,只要用逗号隔开就行。 #所有类型的形参都可以加,但是一般使用匿名函数只是加位置参数,其他的用不到 func = lambda a,b,*args,sex= 'alex',c,**kwargs: kwargs print(func(3, 4,c=666,name='alex')) # {'name': 'alex'}
    4. 返回值在冒号之后设置,返回值和正常的函数一样,可以是任意数据类型。
    5. 匿名函数不管多复杂.只能写一行.且逻辑结束后直接返回数据.

    练习: def func(a,b): return a b print(func(4,5)) # 构建匿名函数 func1 = lambda a,b: a b print(func1(1,2))

    • 接收一个可切片的数据,返回索引为0与2的对应的元素(元组形式)。
    • func2 = lambda a: (a[0],a[2]) print(func2([22,33,44,55])) #(22,44) print(func2('asdfg')) #('a', 'd')
    • 写匿名函数:接收两个int参数,将较大的数据返回。
    • func = lambda a,b: a if a > b else b print(func(5,7)) # 7
    1. 内置函数 # # python 提供了68个内置函数。 reversed() 内建函数将返回一个反序访问的迭代器。 enumerate() 内建函数同样也返回迭代器。 和range类似,map 、zip以及filter内置函数在Python 3.0 中也转变成迭代器以节约内存空间。 #print() ''' 源码分析 def print(self, *args, sep=' ', end='n', file=None): # known special case of print """ print(value, ..., sep=' ', end='n', file=sys.stdout, flush=False) file: 默认是输出到屏幕,如果设置为文件句柄,输出到文件 sep: 打印多个值之间的分隔符,默认为空格 end: 每一次打印的结尾,默认为换行符 flush: 立即把内容输出到流文件,不作缓存 """ ''' print(1,2,3,4)#1 2 3 4 print(1,2,3,4,sep='&')#1&2&3&4 print(1,2,3,sep='*')#1*2*3 print(111,end='') print(222)#两行的结果:111222 f = open('log','w',encoding='utf-8') print('写入文件',file=f,flush=True) #int() #str() #bytes() 把字符串转换成bytes类型 # 将字符串转换成字节 s = '你好' bs = bytes(s,encoding='utf-8') print(bs) #b'xe4xbdxa0xe5xa5xbd' # 将字节转换成字符串 bs = b'xe4xbdxa0xe5xa5xbd' s1 = str(bs,encoding='utf-8') print(s1) #你好 #bool() #set() # list() 将一个可迭代对象转换成列表 l1 = list() #空列表 l2 = list('abcd') print(l2)#['a', 'b', 'c', 'd'] #tuple() 将一个可迭代对象转换成元组 tu1 = tuple('abcd') print(tu1)#('a', 'b', 'c', 'd') # dict 创建字典的几种方式 # 直接创建 dic = {'name': '太白', 'age': 18} # 元组的解构 dic = dict([(1,'one'),(2,'two'),(3,'three')] # dic = dict(one=1,two=2,three=3) print(dic)#{'one': 1, 'two': 2, 'three': 3} # fromkeys dic = { k: v for k,v in [('one', 1),('two', 2),('three', 3)]} print(dic)#{'one': 1, 'two': 2, 'three': 3} # update dic = {} dic.update([(1, 'a'), (2, 'b'), (3, 'c'), (4, 'd')]) print(dic)#{1: 'a', 2: 'b', 3: 'c', 4: 'd'} # 字典的推导式 dic = { k: v for k,v in [('one', 1),('two', 2),('three', 3)]} print(dic)#{'one': 1, 'two': 2, 'three': 3} lst1 = ['jay', 'jj', 'meet'] lst2 = ['周杰伦','林俊杰','元宝'] dic = { lst2[i]: lst1[i] for i in range(len(lst1))} print(dic)#{'周杰伦': 'jay', '林俊杰': 'jj', '元宝': 'meet'} # dic = dict(zip(['one', 'two', 'three'],[1, 2, 3])) print(dic)#{'one': 1, 'two': 2, 'three': 3} # abs() 返回绝对值*** i = -5 print(abs(i))#5 print(abs(-6)) # sum()求和【针对数字】,可以设置初始 *** print(sum([1.1,2.4,3.88]))#7.38 print(sum([1,2,3]))#6 print(sum((1,2,3),100))#106 可以设置初始值,让初始值为100 l1 = [i for i in range(10)] print(sum(l1))#45 print(sum(l1,100))#145 s1 = '12345' #字符串 print(sum(s1)) # 错误 # reversed 返回的是一个翻转的迭代器(将一个序列翻转, 返回翻转序列的迭代器) *** l1 = [i for i in range(10)] l1.reverse() # 列表的方法 print(l1)#[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]#对原列表操作 ret = reversed([1, 4, 3, 7, 9]) print(list(ret)) # [9, 7, 3, 4, 1] l1 = [i for i in range(10)] obj = reversed(l1) #将可迭代对象转化为迭代器 返回的是迭代器 print(obj)#<list_reverseiterator object at 0x000002092EC877F0> print(l1)#[0, 1, 2, 3, 4, 5, 6, 7, 8, 9] #原列表不变 print(list(obj))#[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]转化为列表进行取值 # zip 拉链方法 ***面试题会考 函数用于将可迭代的对象作为参数,将对象中对应的元素打包成一个个元组,然后返回由这些元组组成的内容,如果各个迭代器的元素个数不一致,则按照长度最短的返回。 l1 = [1, 2, 3, 4, 5] tu1 = ('太白', 'b哥', '德刚') s1 = 'abcd' obj = zip(l1,tu1,s1) print(obj)#<zip object at 0x00000284D0211088> python内部提供的迭代器 for i in obj: print(i) #结果: (1, '太白', 'a') (2, 'b哥', 'b') (3, '德刚', 'c') 或: print(list(obj))#[(1, '太白', 'a'), (2, 'b哥', 'b'), (3, '德刚', 'c')] # ************* 以下方法最最最重要 # min()求最小值 和 max()求最大值 # 返回此序列最小值 l1 = [33, 2, 3, 54, 7, -1, -9] print(min(l1))#-9 print(min([1,2,-5]))#-5 # 以绝对值的方式获取最小值 #1:求最小的绝对值 l1 = [33, 2, 3, 54, 7, -1, -9] l2 = [] func = lambda a: abs(a) for i in l1: l2.append(func(i)) print(l2)#[33, 2, 3, 54, 7, 1, 9] print(min(l2)) #1 #2:找出绝对值最小的元素 #自己写函数 l1 = [33, 2, 3, 54, 7, -1, -9] def abss(a): return abs(a) print(min(l1,key=abss)) #-1 #直接用内置函数abs() l1 = [33, 2, 3, 54, 7, -1, -9] print(min(l1,key=abs))#-1 print(min([1,2,-5,],key=abs)) #1 ## key=函数名,按照绝对值的大小,返回此序列最小值 print(min(-5,6,-3,key=lambda x:abs(x)))# -3 可以设置很多参数比较大小 【凡是可以加key的:它会自动的将可迭代对象中的每个元素按照顺序传入key对应的函数中,以返回值比较大小。】 【 min函数循环的是什么,返回的就是什么。正常情况下:列表:返回列表中的元素。字典:返回字典的键。】 【 加key,是可以加'函数名',min自动会获取传入min函数中的参数的每个元素,然后通过函数的返回值比较大小((key=函数名,看该函数返回的是什么。按照什么比较大小,就将什么设置为返回值),返回最小的返回值对应的那个传入参数的元素。】 dic = {'a': 3, 'b': 2, 'c': 1} # 求出值最小的键 print(min(dic)) #a min默认会按照字典的键去比较大小。 #按照字典的值比较大小 #1: dic = {'a':3,'b':2,'c':1} def func(a): return dic[a] #key对应的函数的返回值是什么,就按什么比较大小 print(min(dic,key=func))#c #2:min函数按照什么循环,lambda函数的参数位置就写什么。后面的返回值是根据它转化的。 dic = {'a':3,'b':2,'c':1} func = lambda a :dic[a] print(min(dic,key=func))#c #简化: # a为dic的key,按lambda的返回值(即dic的值dic[a])进行比较,返回最小的值对应的键。 dic = {'a':3,'b':2,'c':1} print(min(dic,key=lambda a:dic[a])) # c 字典中最小值对应的键。min函数循环的是什么,返回的就是什么。按键循环 print(dic[min(dic,key=lambda a:dic[a])]) #1 字典中最小的值 l2 = [('太白', 18), ('alex', 73), ('wusir', 35), ('口天吴', 41)] print(min(l2)) #('alex', 73) #min函数返回元组,它循环的是什么,返回的就是什么。默认按照列表中每个元组中第一个元素的首字母的Unicode比较 #自定制, key print(min(l2,key=lambda x:x[1]))#('太白', 18) print(min(l2,key=lambda x:x[1])[0])#太白 print(min(l2,key=lambda x:x[1])[1])#18 # max最大值 与最小值用法相同 # sorted 排序函数(可加key自定制) 语法:sorted(iterable,key=None,reverse=False) iterable : 可迭代对象 key: 排序规则(排序函数),在sorted内部会将可迭代对象中的每一个元素传递给这个函数的参数.根据函数运算的结果进行排序 reverse :是否是倒叙,True 倒叙 False 正序 l1 = [22, 33, 1, 2, 8, 7, 6, 5] l2 = sorted(l1) print(l1)#[22, 33, 1, 2, 8, 7, 6, 5]原列表不会改变 print(l2)#[1, 2, 5, 6, 7, 8, 22, 33] #倒序: lst = [1,3,2,5,4] lst3 = sorted(lst,reverse=True) print(lst3) #[5, 4, 3, 2, 1] #字典使用sorted排序 dic = {1:'a',3:'c',2:'b'} print(sorted(dic)) # 字典排序返回的就是排序后的key [1, 2, 3] l2 = [('大壮', 76), ('雪飞', 70), ('纳钦', 94), ('张珵', 98), ('b哥',96)] print(sorted(l2))#[('b哥', 96), ('大壮', 76), ('张珵', 98), ('纳钦', 94), ('雪飞', 70)] print(sorted(l2,key= lambda x:x[1])) # [('雪飞', 70), ('大壮', 76), ('纳钦', 94), ('b哥', 96), ('张珵', 98)]返回的是一个列表,默认从低到高 print(sorted(l2,key= lambda x:x[1],reverse=True)) #[('张珵', 98), ('b哥', 96), ('纳钦', 94), ('大壮', 76), ('雪飞', 70)] #和函数组合使用 #定义一个列表,然后根据元素的长度排序 lst = ['天龙八部', '西游记', '红楼梦', '三国演义'] #计算字符串的长度 def func(s): return len(s) print(sorted(lst, key=func))#['西游记', '红楼梦', '天龙八部', '三国演义'] #和lambda组合使用 lst = ['天龙八部', '西游记', '红楼梦', '三国演义'] print(sorted(lst, key=lambda s: len(s)))#['西游记', '红楼梦', '天龙八部', '三国演义'] #按照年龄对学生信息进行排序 lst = [{'id': 1, 'name': 'alex', 'age': 18}, {'id': 2, 'name': 'wusir', 'age': 17}, {'id': 3, 'name': 'taibai', 'age': 16}, ] print(sorted(lst, key=lambda e: e['age']))#[{'id': 3, 'name': 'taibai', 'age': 16}, {'id': 2, 'name': 'wusir', 'age': 17}, {'id': 1, 'name': 'alex', 'age': 18}] # filter()筛选过滤 类似于列表推导式的筛选模式 返回的是迭代器 语法: filter(function, iterable) function: 用来筛选的函数, 在filter中会自动的把iterable中的元素传递给function, 然后根据function返回的True或者False来判断是否保留此项数据 iterable: 可迭代对象 lst = [{'id': 1, 'name': 'alex', 'age': 18}, {'id': 1, 'name': 'wusir', 'age': 17}, {'id': 1, 'name': 'taibai', 'age': 16}, ] ls = filter(lambda e: e['age'] > 16, lst) #返回的是迭代器 print(list(ls))#转化成列表 [{'id': 1, 'name': 'alex', 'age': 18}, {'id': 1, 'name': 'wusir', 'age': 17}] #列表推导式的筛选模式 l1 = [2, 3, 4, 1, 6, 7, 8] print([i for i in l1 if i > 3]) # 返回的是列表 l1 = [2, 3, 4, 1, 6, 7, 8] ret = filter(lambda x: x > 3,l1) # 返回的是迭代器 print(ret)#<filter object at 0x00000165B06D7F28> print(list(ret))#[4, 6, 7, 8] # map() 映射函数 类似于列表推导式的循环模式 返回的是迭代器 语法: map(function,iterable) 可以对可迭代对象中的每一个元素进映射,分别取出来执行function #列表推导式的循环模式 print([i**2 for i in range(1,6)]) # 返回的是列表 #[1, 4, 9, 16, 25] #计算每个元素的平方,返回新列表 ret = map(lambda x: x**2,range(1,6)) # 返回的是迭代器 print(ret)#<map object at 0x00000191237C7EB8> print(list(ret))#[1, 4, 9, 16, 25] # 计算两个列表中相同位置的数据的和 lst1 = [1, 2, 3, 4, 5] lst2 = [2, 4, 6, 8, 10] print(list(map(lambda x, y: x y, lst1, lst2)))#[3, 6, 9, 12, 15] # reduce # 在Python2.x版本中recude是直接 import就可以的, Python3.x版本中需要从functools这个包中导入 # reduce 的使用方式:reduce(函数名,可迭代对象) # 这两个参数必须都要有,缺一个不行 from functools import reduce def func(x,y): return x y ret = reduce(func,[3,4,5,6,7]) print(ret) # 结果 25 #普通函数版 from functools import reduce def func(x,y): return x * 10 y l = reduce(func,[1,2,3,4]) print(l)#1234 第一次的时候 x是1, y是2 x乘以10就是10,然后加上y也就是2最终结果是12然后临时存储起来了 第二次的时候x是临时存储的值12 x乘以10就是 120 然后加上y也就是3最终结果是123临时存储起来了 第三次的时候x是临时存储的值123 x乘以10就是 1230 然后加上y也就是4最终结果是1234然后返回了 #匿名函数版 from functools import reduce l = reduce(lambda x,y:x*10 y,[1,2,3,4]) print(l)#1234 from functools import reduce def func(x,y): return x y l = reduce(func,[11,2,3,4]) #第一次的时候取2个数据,之后都取1个。 print(l) ''' 第一次:x y : 11 2 x y = 记录: 13 第二次:x = 13 y = 3 x y = 记录: 16 第三次 x = 16 y = 4 ....... '''
    2. 闭包: 整个历史中的某个商品的平均收盘价。什么叫平局收盘价呢?就是从这个商品一出现开始,每天记录当天价格,然后计算他的平均值:平均值要考虑直至目前为止所有的价格。 比如大众推出了一款新车:小白轿车。 第一天价格为:100000元,平均收盘价:100000元 第二天价格为:110000元,平均收盘价:(100000 110000)/2 元 第三天价格为:120000元,平均收盘价:(100000 110000 120000)/3 元

# 封闭的东西: 保证数据的安全。 # 方案一: l1 = [] # 全局变量 数据不安全 li = [] def make_averager(new_value): l1.append(new_value) total = sum(l1) averager = total/len(l1) return averager print(make_averager(100000)) print(make_averager(110000)) .....(多行代码) l1.append(666) print(make_averager(120000)) print(make_averager(90000)) # 方案二: 数据安全,l1不能是全局变量。 # 每次执行的时候,l1列表都会重新赋值成[] li = [] def make_averager(new_value): l1 = [] l1.append(new_value) total = sum(l1) averager = total/len(l1) return averager print(make_averager(100000)) print(make_averager(110000)) .....(多行代码) print(make_averager(120000)) print(make_averager(90000)) # 方案三: 闭包 #在函数中嵌套了一个函数。avg 这个变量接收的实际是averager函数名,也就是其对应的内存地址,我执行了三次avg 也就是执行了三次averager这个函数。 def make_averager(): l1 = [] def averager(new_value): l1.append(new_value) print(l1) total = sum(l1) return total/len(l1) return averager avg = make_averager() # 【重点理解】返回值averager给avg avg得到了内层函数的内存地址,所以外层函数执行完后,只要有内层函数的内存地址,下面的print语句依然可以执行内层函数 print(avg(100000)) print(avg(110000)) print(avg(120000)) print(avg(190000)) ## 函数名.__code__.co_freevars 查看函数的自由变量 print(avg.__code__.co_freevars)#('l1',) # 函数名.__code__.co_varnames 查看函数的局部变量 print(avg.__code__.co_varnames)#('new_value', 'total') #获取具体的自由变量对象,也就是cell对象。 print(avg.__closure__)#(<cell at 0x0000029744E374C8: list object at 0x0000029744ECE948>,) #cell_contents 自由变量具体的值 print(avg.__closure__[0].cell_contents)#[] def func(): return 666 print(func)#<function func at 0x00000219A46C9AE8> 函数名指向函数的内存地址 print(globals())#不包含 'ret': 666 ret = func() print(globals())#包含 'ret': 666 闭包: 多用于面试题: 什么是闭包? 闭包有什么作用。 闭包的定义: 1,闭包只能存在嵌套函数中。闭包是嵌套在函数中的函数 2,闭包必须是内层函数对外层函数非全局变量的引用(使用),就会形成闭包。【使用:可改变 引用:直接使用,如print()】 自由变量:被引用的非全局变量也称作自由变量,这个自由变量会与内层函数产生一个绑定关系,自由变量不会在内存中消失,而且全局还引用不到。 闭包的作用:保证数据的安全。保存局部信息不被销毁,保证数据的安全性。 闭包的应用:可以保存一些非全局变量但是不易被销毁、改变的数据。装饰器 # 如何判断一个嵌套函数是不是闭包 1,闭包只能存在嵌套函数中。 2,内层函数对外层函数非全局变量的引用(使用),就会形成闭包。 # 例1:是闭包 def wrapper(): a = 1 #a是自由变量 def inner(): print(a) return inner ret = wrapper() # 例2:也是闭包!【讲】 def wrapper(a,b): #传参相当于a=2,b=3,相当于在函数内重新定义变量,所以a,b都是外层函数的非全局变量,即a,b都是自由变量 def inner(): print(a) print(b) return inner a = 2 b = 3 ret = wrapper(a,b) print(ret.__code__.co_freevars) # ('a', 'b') #用几个就有几个自由变量 print(ret.__closure__)#(<cell at 0x000001F3155274C8: int object at 0x00000000513A6C30>, <cell at 0x000001F3155274F8: int object at 0x00000000513A6C50>) print(ret.__closure__[0].cell_contents)# 2 print(ret.__closure__[1].cell_contents)# 3 #例3: def wrapper(): count = 1 # 不可变数据类型 def inner(): nonlocal count #count是自由变量 count = 1 print(count) # 1 inner() print(count) # 2 return inner ret = wrapper() print(ret.__code__.co_freevars)#('count',) # 如何代码判断闭包? def make_averager(): l1 = [] #l1是自由变量 def averager(new_value): l1.append(new_value) print(l1) total = sum(l1) return total/len(l1) return averager avg = make_averager() # averager print(avg.__code__.co_freevars)

  1. 总结
    • 匿名函数。
    • 内置函数。*** 一定要记住,敲3遍以上。 ** 尽量记住,2遍。
    • 闭包:多用于面试题: 什么是闭包? 闭包有什么作用。

0 人点赞