闭包
Python允许函数进行嵌套定义,即一个函数的内部可以继续定义其他的函数,将外部函数作为其内部嵌套函数的引用环境,并且在对内部函数进行处理的时候外部函数的引用环境一直都会不变,这种将内部函数与外部函数作为整体处理的函数嵌套结构在程序设计中称为闭包(closure)。
实例:定义函数闭包结构
# coding:UTF-8 def outer_add(n1): def inner_add(n2): return n1+n2 return inner_add #返回内部函数引用; oa=outer_add(10) #接受外部函数引用; print("加法计算结果: %d" % oa(20)) #执行内部函数; print("加法计算结果: %d" % oa(30)) 显示结果: 加法计算结果: 30 加法计算结果: 40
本程序实现了一个闭包操作,在outer_add()函数中嵌套了一个内部函数,在使用外部参数的时候,我们往往要先进行对外部函数引用,这样才能实现对内部函数的调用,于是我们用了oa来接收外部函数的引用,然后继续对oa操作,这时表示的就是对内部函数的使用。
实例:内部函数修改外部函数变量类容
使用闭包结构的最大特点时可以保持外部函数操作的状态,但是如果要想在内部函数中修改外部函数中定义的局部变量或参数的类容,则必须使用nonlocal关键字.
实例:
# coding:UTF-8 def print_data(count): def out(data): nonlocal count #修改外部函数变量; count+=1 return "第{}次输出数据:{}".format(count,data) return out oa=print_data(0) print(oa("www.Python.com")) print(oa("Python")) print(oa("good!")) 显示结果: 第1次输出数据:www.Python.com 第2次输出数据:Python 第3次输出数据:good!
lambda表达式
在Python中所有定义的函数都会提供一个函数名称,实际上提供函数名称就是为了方便函数进行调用,然而在某些情况下,函数可能只调用一次,这样的函数就被称为匿名函数,匿名函数需要lambda关键字进行定义。
# coding:UTF-8 sum=lambda x,y:x+y; #定义一个匿名函数,实现两个数字相加(x,y); print(sum(2,3))
通过程序我们可以发现,我们在使用lambda的时候,我们不需要使用return也可以直接返回计算结果。当然也可以不用写函数名称。
实例:结合闭包使用lambda表达式
def add(n1): return lambda n2:n2+n1 oper=add(100) print(oper(30))
我们在使用的lambda表达式的时候一般都是为了程序简单化,减少代码量,也减少了不必要的繁琐。
主函数
学过c语言的同学应该知道每一个程序最后的实现都是在主函数中,但是在python中并没有提供主函数的定义结构,如果有需要,用户可以自己定义,此时就可以基于“name”这个系统变量来实现此类操作。
实例:定义主函数并观察_name_
def main(): print("自定义程序主函数,表示程序执行的起点!") print("更多知识请关注“csdn博主:心随而动”") if __name__=="__main__": main()
内置对象函数
函数 |
描述 |
callable(object) |
判定给定的对象是否可以调用,如果可以调用,则返回True,否则返回False |
eval(object,【,globals[]】) |
对给定的对象(可能是字符串或编译对象)进行单行代码计算,可以选择性地址传递全局变量或局部变量信息. |
exec(source,filename,mode) |
对给定的对象(可能是字符串或编译对象)进行多代码计算,可以选择性的传递全局变量或者局部变量信息(类型必须为字典) |
complie(source,filename,mode) |
对传入的source数据进行编译,可以通过filename指定所需要编译的代码文件(一般为空),在编译时需要明确指明运行模式,该选项有三种配置:(1).mode=“eval”:使用eval函数执行代码() ,(2).mode=“single”:使用single()函数执行代码,(3).mode=“exec”:使用exec函数执行代码 |
一.callable()函数
在Python中,对函数或者变量都是引用传递,所以为了判断某些操作结构是否可以被调用,就可以通过callable()函数实现。
# coding:UTF-8 print("input()函数是否可以被调用:%s" % callable(input)) print("Hello字符串是否可以被调用:%s" % (callable("Hello"))) def get_info(): return "I like Python" temr_fun=get_info print("函数get_info是否可以被调用:%s" % (callable(get_info))) print("函数temr_fun是否可以被调用:%s" % (callable(temr_fun))) 运行结果: input()函数是否可以被调用:True Hello字符串是否可以被调用:False 函数get_info是否可以被调用:True 函数temr_fun是否可以被调用:True
二.eval()函数
程序事多个表达式的集合,在Python中开发者可以将要执行的表达式直接定义成字符串的形式,随后使用eval()函数动态的编译和执行,如图:
例:使用eval()函数动态编译并执行表达式
num=10 result=eval("3*num") #直接解析字符串定义的程序表达式 print("计算结果为:%d" % (result))
在使用eval()函数执行时,也可以将程序中的 全局变量或局部变量传递到eval()函数执行的表达式中,但是要求这些变量必须以字典的形式传递。
实例:使用全局变量
num=10 result=eval("3*num") #直接解析字符串定义的程序表达式 print("计算结果为:%d" % (result)) global_num=10 global_str="数据加法计算结果:{}" var_dict=dict(num=global_num,info=global_str) #字典数据表示全局变量 result=eval("info.format(num*2)",var_dict) 程序运行结果: 数据加法计算结果:20
在序列的定义中,字符串可以转换为列表,元组,字典,但是要完成此功能需要通过不同的转换函数进行处理,而这一转换功能也可以直接利用eval()函数统一实现。
实例:
list_str="[1,2,3]" #列表结构字符串; tuple_str="{1,2,3}" #元组结构字符串 dict_str="{1:'one',2:'two',3:'three'}" #字典结构字符串 list_eval=eval(list_str) #字符串转换为列表 tuple_eval=eval(tuple_str) dict_eval=eval(dict_str) print("[list]序列结构:%s,序列类型:%s" % (list_eval,type(list_eval))) print("[tuple]序列结构:%s,序列类型:%s" % (tuple_eval,type(tuple_eval))) print("[dict]序列结构:%s,序列类型:%s" % (dict_eval,type(dict_eval)))
exec()函数
与eval()函数功能类似的还有一个函数,即exec()函数,该函数也可以更具字符串定义的程序表达式动态的编译和运行。
实例:
statement="for item in range(1,10,2):" \ "print(item,end=',')" exec(statement) 代码显示结果: 1,3,5,7,9
提示:eval()函数和exec()函数的区别
(1).eval函数只能执行一个简单的表达式,并且可以接受表达式返回的值。
(2).exec函数可以执行多行程序语句,但是不能接受函数的返回值,返回的事None。
compile()函数
eval()和exec()两个函数在执行字符串中表达式的操作时,都采用先编译再执行的模式完成,但是这样的实现方式可能会对程序性能有所影响。为了提高再运行时生成代码对象的速度。Python提供了compile()函数,此函数可以直接在源代码程序编译时就自动对字符串中表达式进行解析,而在程序运行的时候将不再进行动态编译,而实直接执行编译好的对象。
实例:使用eval模式
代码:
statement="100+200+50-30" code_eval=compile(statement,"","eval") #使用eval模式 result=eval(code_eval) print("计算结果:%d" % result)
实例:使用single执行模式
input_data=None statement="input_data=input('请输入你最喜欢的学校:')" code_exec=compile(statement,"","single") #使用single执行模式 exec(code_exec) print("输入数据为:%s" % (input_data))
本程序通过字符串定义的是一个完整的语句,不再是一个简单的表达式,所以compile()函数中定义的执行模式可以是single或exec,由于只有单行语句,所以使用single模式并用exec函数执行编译对象。
实例:使用exec模式
infos=[] #保存全部键盘输入数据 statement="for item in range(2):"\ "infos.append(input('请输入你要输入的数据:'))" code_eval=compile(statement,"","exec") exec(code_eval) exec("print('经常访问的网址是:%s' % infos)")
总结
1.函数是一段可以重复调用的代码段,Python中定义函数统一使用def关键字进行定义,如果需要有返回值,则直接在函数中添加return语句即可实现。
2.Python中定义的函数支持多种参数类型(具体的看前面的解析)
3. 在函数中使用参数时需要注意全局变量与局部变量的概念,全局变量可以利用关键字global定义。
4. 函数允许嵌套定义,嵌套后的函数可以方便的实现外部状态的维护,这样的函数嵌套结构就被称为闭包处理。如果要在函数中对外部函数的变量进行修改,就要用nonlocal关键字。
5. 使用lambda表达式可以定义匿名函数,lambda函数的函数体比较简单。如果定义的函数其函数体中有多行代码,建议定义为有名函数。
6. 一个函数允许调用自己,这样的处理方式就是递归调用。
7. Python中可以使用eval,exec函数动态的解析字符串中提供的表达式或代码,也可以使用compile()函数对要执行的代码提前翻译,以提高程序的执行能力。