python学习[第十八篇] 函数二 (未完)
python学习[第十八篇] 函数二
函数式编程
匿名函数与lambda
lambda [arg1,[arg2,arg3,...,argN]: expression
python允许lambda关键字创造匿名函数。匿名函数不需要以标准的方式来声明,比如def语句。然后作为函数它可以有参数。一个完整的lambda语句代表了一个表达式,这个表达式的定义体必须和声明放在同一行。参数是可选的,如果使用参数的话,参数通常也是表达式的一部分。
虽然lambda是一个函数的单行版本,lambda表达式运作起来就像一个函数,当被调用时,创建一个框架对象。
内建函数 apply() filter() map() reduce()
apply(func,[,nkw][,kw]) 用可选的参数来调用func,nkw 为非关键字参数,kw为关键字参数;返回值是函数调用的返回值。
filter(func,seq) 调用一个布尔函数func来迭代遍历每个seq的元素,返回一个是func返回值为True的元素的序列。
map(func,seq1[,seq2]) 将函数func作用域给定序列s的每个元素,并用一个列表来提供返回值,如果func为None,func表现为一个身份函数,返回一个含有每个序列中元素集合的n个元组的列表。
filter 给定一个对象的序列和一个过滤函数,每个序列元素都通过这个过滤器进行筛选,保留函数返回威震的对象。filter函数为已知的序列的每个元素调用给定布尔函数。每个filter返回的非零(true)值元素添加到一个列表中。返回的对象是一个从原始队列中的过滤后的队列。
reduce(func,seq[,init])
reduce使用了一个二元函数(一个接收带两个值作为输入,进行了一些计算然后返回一个值作为输出),一个序列和一个可选的初始化器,卓有成效地将那个列表的内容减少为一个单一的值,他通过取出序列的头两个元素,将他们传入二元函数来获得一个单一的值来实现,然后又用这个值和序列的下一个元素来获得又一个值,然后知道整个序列的内容都遍历完毕以及最后的值会被计算出来为止。
>>> print filter(lambda x:x %2 ,range(5)) [1, 3] >>> print map(lambda x,y:x+y,range(5),range(5)) [0, 2, 4, 6, 8] >>> print reduce((lambda x,y:x+y),range(5)) 10
偏函数应用
Currying能繁华成为偏函数应用(partial function application PFA)这种函数将任意数量(顺序)的参数的函数转化成灵感一个带剩余参数的函数对象。
>>> from operator import add,mul >>> from functools import partial >>> add1=partial(add,1) >>> nul100=partial(mul,100) >>> add1(10) 11 >>> int('5',base=8) 5 >>> int('15',base=16) 21 >>> mul100=partial(mul,100) >>> mul100(10) 1000 >>> baseTwo=partial(int,base=2) >>> baseTwo('10101') 21 from functools import partial import Tkinter root=Tkinter.Tk() MyButton=partial(Tkinter.Button,root,fg='white',bg='blue') b1=MyButton(text='Button 1') b2=MyButton(text='Button 2') qb=MyButton(text='QUIT',bg='red',command=root.quit) b1.pack() b2.pack() qb.pack(fill=Tkinter.X,expand=True) root.title('PFAs!') root.mainloop()
变量作用域
标识符的作用域是定义为其声明在程序里的可应用范围,或者即使我们所说的变量可见性。变量可以是局部域或者全局域。
全局变量与局部变量
定义在函数内的变量有局部作用域,在一个模块中最高级别的变量有全局作用域。
声明适应的程序的范围被称为了声明的作用域。在一个过程中,如果名字在过程的声明之内,他的出现即为过程的局部变量;否则的话,出现即为非局部。
全局变量的一个特征是除非被删除掉,否则他们的存活到脚本运行结束,且对于所有的函数,他们的值都是可以被访问的,然而局部变量,就像他们存放的栈,暂时地存在,仅仅只依赖于定义它们的函数现阶段是否处于活动。当一个函数调用出现时,其局部变量就进入声明他们的作用域。在那一刻,一个新的局部变量名为那个对象创建了,一旦函数完成,框架被释放,变量将会离开作用域。
global_str='foo' def foo(): local_str='bar' return global_str+local_str
以下情况会报错:
count=10 def outer(): count=count+1 outer() D:/programSoft/PyCharm_pro/projects/pro/func.py Traceback (most recent call last): File "D:/programSoft/PyCharm_pro/projects/pro/func.py", line 4, in <module> outer() File "D:/programSoft/PyCharm_pro/projects/pro/func.py", line 3, in outer count=count+1 UnboundLocalError: local variable 'count' referenced before assignment Process finished with exit code 1
global 语句
如果全局变量的名字声明在一个函数体内的时候,全局变量的名字能被局部变量覆盖掉。
>>> foo=5 >>> m=1 >>> def foo(): ... m=3 ... def bar(): ... n=4 ... print m ... print m ... >>> foo() 3
nonlocal 语句 和global语句对内部变量的外部但非global的变量进行调用
count=10 def outer(): count=20 def inner(): nonlocal count count=30 print(count) inner() print(count) outer() print(count) D:/programSoft/PyCharm_pro/projects/pro/func.py 30 inner 30 outer 10 global
闭包
如果在一个内部函数里,对在外部作用域(担不是在全局作用域)的变量进行引用,那么内部函数就被认为是闭包(closure)。定义在外部函数内的但由内部函数引用或者使用的变量被称为自由变量。闭包将内部函数自己的代码和作用域以及外部函数的作用结合起来。闭包的词法变量不属于全局名称空间或者局部--而属于其他的名称空间,带着流浪的作用域。
简单闭包的例子
>>> def counter(start_at = 0) : ... count = [start_at] ... def incr(): ... count[0]+=1 ... return count[0] ... return incr ... >>> count=counter(5) >>> print count() 6 >>> print count() 7 >>> print count() 8 >>> count=counter(100) >>> print count <function incr at 0x02BEABB0> >>> print count() 101
作用域和lambda
一个lambda表达式定义了新的作用域。就像函数的定义,所以这个作用域除了局部lambda函数,对于程序其他部分,该作用都是不能对进行访问的。那些声明为函数局部变量的lambda表达式这个函数体内是可以访问的,然而在lambda语句的表达式和函数相同的作用域。
作用域和名称空间