函数(匿名函数,嵌套函数,高阶函数,装饰器)
Posted zjaiccn
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了函数(匿名函数,嵌套函数,高阶函数,装饰器)相关的知识,希望对你有一定的参考价值。
函数:函数是指将一组语句的集合通过一个名字(函数名)封装起来,要想执行这个函数,只需要调用其函数名即可。
特性: 减少重复代码 是程序变的可扩展 是程序变得易维护
函数参数:
参数可以让你的函数变得跟灵活,不只你能做死循环的动作,还可以根据调用时传参的不同来决定函数内部的执行流程
形参变量
只有在被调用的时候才分配内存单元,,在调用结束时,即可释放所分配的内存单元,因此,形参只在函数内部有效,函数调用结束返回主调用函数后则不能再使用该形参变量
实参
可是常量,变量,表达式,函数等,无论实参是何种类型的量,再进行函数调用时,他们都必须有确定的值,以便把这些值传送给形参。
Def calc(x,y): x,y 形参
Res = x**y
Retrun res
C = calc(a,b) a,b 实参
默认参数必须要放在位置参数的后边。 def function(name ,age ,course,city=’北京’)
关键参数 def function(name,age,course=’py’,country=‘cn’) function(’张鉴’,course=’py’,age=22,country=’KOR’)
非固定参数 -- 方式一 以元祖形式的
def send_alert(msg,*args): #*之后的可以有很多同类型的参数,打包成元祖,例如账户邮箱等 for u in args: print(‘warning!!!‘,u,msg) send_alert(‘error!!‘,‘alex‘,‘ccn‘,‘zj‘)
非固定参数 -- 方式二 非固定参数必须放在最后习惯
uz = [‘pig‘,‘ccn‘,‘zj‘] def send_alert(msg,*user): for u in user: print(‘warning!!!‘,u,msg) send_alert(‘error!!‘,*uz)
传字典 就用**
def func(name,*args,**kw): #**is dic -zidian print(name,args,kw) dic = {‘ccn‘:‘zj‘} func(‘alex‘,22,‘mashaladi‘,‘50w‘,addr=‘shandong‘,num=31344141,**dic)
函数-返回值
函数外部的代码想要获取函数执行的结果,就可以在函数里用return语句把结果返回
retrun 代表一个函数的结束 ,只要碰到retrun就结束,后边有多少代码都不执行了
函数-局部变量
指定义在函数里边的变量 ,只能在局部生效,函数一点执行结束,变量就消失了在内存里
定义在函数顶层的一级代码的变量,为全局变量。全局变量,全部代码都可以调用
如果想在函数中使用修改全局变量可以使用global -- 不建议使用,一般情况下不用
函数-函数中修改列表中的数据
names = [‘Alex‘,‘Black‘,‘Peiqi‘] def change_name(): #global names del names[2] names[1] = ‘Write‘ names = [‘123’,’465’] #这个是不可以修改的,如果想要修改就要加上global print(names) change_name() print(names)
函数-嵌套函数
def func1(): print(‘Alex‘) def func2(): print(‘Peiqi‘) func2() func1( )
函数要想执行 必须被调用
函数-作用域
在Python中一个函数就是一个作用域,局部变量其实就是放在作用域中
代码写完之后作用域就生成了,无论函数在哪里调用了,被如何调用了,都会回到最初定义的地方进行向上查找。
函数- 匿名函数 lambda
def calc(x,y): if x > y: return x**y else: return x/y func = lambda x,y:x**y if x < y else x/y #shengming anonymous function print(func(3,3)) print(calc(3,3))
函数-高阶函数
变量可以指向函数,函数的参数能接收变量,那么一个函数就可以接收另一个函数作为参数,这种函数就称之为高阶函数
可以将函数当做一个函数参数传进来就是高阶函数
只需要满足任意一个条件,即是高阶函数 1.接收一个或多个函数作为输入参数2.return 返回另外一个函数
递归介绍 --递归与栈的关系
递归就是在函数的执行过程中调用自己
def recursion(n): # sum(n) print(n) recursion(n+1) recursion(1)
递归的作用:可以解决一些复杂的数学问题,例如斐波那契,汉诺塔
递归的特点:
1.必须有一个明确的结束条件,否则就会变成死循环,最终撑爆系统内存
2.每次进入更深的一次递归时,问题规模相比上次递归都应有所减少
3.递归执行效率不高,递归层次过多会导致栈溢出
求阶乘
def factorial(n): if n == 1: return 1 return n * factorial(n-1) print(factorial(10))
尾递归优化:
只保留一层函数的栈数据,他的当前层不需要等待上一层的结果,而是当前层就需要当前层的数据,但是在Python中即使你写了尾递归的优化也是没有用的,Python还是会给你保留上千次的递归。但是要明白概念,C语言是有这种优化的。
def cal(n): print(n) return cal(n+1) cal(1)
内置函数 built-in function
abs 求绝对值
all # return True 例如列表中,可能有none,0,all会遍历列表(数据结构)所有元素,只要有一个FALSE,就会显示false
any 与all 相反,只要有一个True 就是True
ascii 返回一个字符的ascii的值
bin 返回一个整数的二进制格式
bool 判断一个数据结构是True or FALSE bool([]) 空列表、集合、元祖、字典就是FALSE
bytearray # 把byte变成bytearray,可修改的数组
bytes # bytes(“中国”,“utf-8”)
callable # 判断一个对象是否可以调用,面向对象用的
chr #返回一个数字的ascii字符, 比如char(97) 返回就是a
Delattr # 面向对象用的
dir 返回一个对象可调用,操作的属性,功能
divmod #返回除法的商和余数
enumerate # 返回列表的索引和元素,比如 d = [“alex”,”jack”],enumerate(d) 之后得到(0,”alex”)(1,”jack”)
eval # 可以把字符串形式的list,dict,set等,转换成原有的数据类型
exec # 把字符串格式的代码 ,进行解释并执行,比如exec("print(‘hello world‘)"), 就是解释成print(‘hello world’) 并执行
exit # 退出程序
filter #对list、dict、set等可迭代的对象进行过滤 ,filter(lambda x: x>10, [1,2,3,4,56,66,77,9,10]),过滤出所有大于10的值 list(filter(lambda x:x > 10,[1,2,3,45,5,5,6,7,77])) [45, 77]
frozenset #将一个集合变成只读
globals #打印全局作用于里的值,全局变量
hash # hash函数
hex #返回一个10进制的16进制表现形式 例如hex(10) 返回’0xa’
id #查看对象内存地址
isinstance #判断一个数据结构的类型 isinstance(a,list) a是数据,list是数据类型 True
map #list(map(lambda x:x**2,a)) a是列表 map类似于filter
max # 求最大值 max(a)
min # 求最小值
Object #面向对象用
oct #8进制数
ord # 返回acsii的字符对应的10进制数 ord(‘a’) 返回97
reversed #可以将列表翻转 和list.reverse() 功能一样
round #可以把小数四舍五入成整数
Sum # 求和 a=[1,2,3] sum(a) 6
Zip # a= [1,2,3] b = [‘a‘,‘b‘,‘c‘] list(zip(a,b)) [(1, ‘a‘), (2, ‘b‘), (3, ‘c‘)]
名称空间 name spase
Name space ,顾名思义就是存放名字的地方 举例说明: 变量 x=1 ,1存放于内存中,那名字x存放在哪里呢?名称空间正式存放名字x与1绑定关系的地方。
Python名称空间有4中 :LEGB
Locals: 函数内部的名字空间,局部变量
Enclosing function:在嵌套函数中外部函数的名字空间,如果fun2嵌套在fun1里,对fun2来说,fun1的名字空间就是enclosing
Globals :当前的模块空间,模块就是一些py文件,也就是说,globals()类似全局变量
_builtins_:内置模块空间,也就是内置变量或内置函数的名字空间,存放内置方法之类的
不同变量的作用域不同就是由这个变量所在的名称空间决定的。
闭包现象
def closure(): name = "alex" def inner(): print("inner",name) return inner func = closure() # retrun inner mem address func()
由于name变量被inner函数调用着,名称空间得不到释放,所以在函数外也可以被调用,这种情况情况叫做闭包
函数进阶:装饰器 ,又称语法糖
在不改变源代码和调用方式的情况下扩展一些新的功能:例如加上认证的模式
# -*- coding:utf-8 -*- account = { ‘is_auth‘ : False, ‘alex‘ : ‘123‘, ‘jack‘ : ‘abc‘ } def login(func): def inner(): if account[‘is_auth‘] is False: username = input(‘username>>‘).strip() password = input(‘password>>‘).strip() if username in account : if password == account[username]: print(‘welcome‘) account[‘is_auth‘] = True func() else : print(‘password is error ,please try again‘) else: print(‘username not found ‘) else: print(‘user already login‘) func() return inner def home(): print("---home page---") @login def tencent(): #login() print(‘---tencetn---‘) def alibaba(): print("---alibaba---") @login def jingdong(): #login() print("---jingdong---") home() tencent = login(tencent) #这里存放的就是inner的内存地址,inner实现了闭包,不会执行里边的func() #print(tencent) jingdong = login(jingdong) tencent() jingdong()
列表生成式
现有个需求,现有列表 a = [1,2,3,4,5,6] 要求你把列表里的每一个值加1. 如何是实现
a = [1,2,3,4,5,6775,9]
a = [i+1 for i in a] # list_builder 列表生成器
print(a)
生成器 -- generator
g = (x * x for x in range(10)) for i in g: print(i)
函数生成器
# -*- coding:utf-8 -*- def febonacci(n): a = 0 b = 1 count = 0 while count < n: tmp = a a = b b = tmp + b #print(b) yield b # 暂停 return count +=1 f = febonacci(20) print(next(f)) print(next(f)) print(next(f)) print(next(f))
用生成器实现并发编程
# -*- coding:utf-8 -*- # def g_test(): # while True: # n = yield # print("receive from outside:",n) # # g = g_test() # g.__next__() # 调用生成器,同时会发送None到yield # # for i in range(10): # g.send(i) # 调用生成器,同时发送i # 通过生成器实现多并发效果,线程就是cpu的执行的任务单元 # 吃包子 c1,c2,c3 消费者 # 生产者 product def cosumer(name): print("comsumer %s ready eat "%name) while True: baozi = yield print("comsumer %s start eat num:%s"%(name,baozi)) c1 = cosumer("c1") c1.__next__() c2 = cosumer("c2") c2.__next__() c3 = cosumer("c3") c3.__next__() for i in range(10): print("we product %s times baozi"%i) c1.send(i) c2.send(i) c3.send(i)
迭代器
我们已经知道,可以直接作用于for循环的数据类型有以下几种:
1.一类是集合数据类型,如list、tuple、dict、set、str等
2.一类generator,包括生成器和带yield的generator function。
这些可直接作用于for循环的对象是否是iterable,可得带的意思就是可遍历、可循环。
可以使用isinstance()判断一个对象是否是Iterable对象。
迭代器 几乎等同于 生成器
以上是关于函数(匿名函数,嵌套函数,高阶函数,装饰器)的主要内容,如果未能解决你的问题,请参考以下文章