Python学习笔记11:Python函数和函数式编程

1、函数vs过程
过程是简单、特殊、没有返回值的函数。Python的过程就是函数,过程默认返回None。

2、调用函数
(1)函数操作符(())
(2)关键字参数
让调用者通过函数调用中的参数名字来区分参数,允许参数缺失或者不按顺序。

def net_conn(host,port):
    net_conn_suite
net_conn('kappa',8080)
net_conn(port=8080,host='chino')

(3)默认参数
默认参数是声明了默认值的参数,允许调用者不向该参数传入值。
(4)参数组
把元组(非关键字参数)或字典(关键字参数)作为参数组传给函数。

func(positional_args,keyword_args,*tuple_grp_nonkw_args,**dict_grp_kw_args)
  • positional_args:位置参数
  • keyword_args:关键字参数
  • tuple_grp_nonkw_args:非关键字参数组(以元组形式体现)
  • dict_grp_kw_args:关键字参数组(以字典形式体现)

3、创建函数
(1)def语句

def function_name(args):
    "function_documentation_string"
    function_body_suite

(2)声明vs定义
Python中,将声明和定义视为一体,函数的子句由声明的标题行以及随后的定义体组成的。
(3)前向引用
Python中不存在前向引用问题(C语言存在,对函数进行的调用必须在函数的定义之后)。
Python中不允许在函数未声明之前,对其进行引用或者调用。
(4)函数属性(2.1)
句点属性标识,命名空间
函数属性是Python中使用句点属性标识并拥有名称空间的一个领域。

def bar():
    pass
bar.__doc__='***'
bar.version=0.1

不能在函数的声明中访问属性,因为此时函数体还没有被创建。
(5)内部/内嵌函数(C#内联函数)
在函数体内创建另一个函数(对象)是完全合法的,这种函数叫做内部/内嵌函数。
闭包:内部函数中包含了在外部函数甚至外部函数之外定义的对象的引用,内部函数会被称为闭包。
(6)函数 (与方法)装饰器
装饰器是在函数调用之上的修饰。

@decorator(dec_opt_args)
def func2Bdecorated(func_opt_args):

2.2中静态方法和类方法语法:

class MyClass(object):
    def staticFoo():
        ...
    staticFoo = staticmethod(staticFoo)

使用装饰器的代码:

class MyClass(object):
    @staticmethod
    def staticFoo():
        ...

装饰器可以“堆叠”起来:

@deco2
@deco1
def func(arg1,arg2,...):
    pass

等价于创建 一个组合函数:

def func(arg1,arg2,...):
    pass
func=deco2(deco1(func))

有参数和无参数的装饰器:

@deco
def foo():pass
=>foo=deco(foo)
@decomaker(deco_args) 
def foo():pass
=>foo=decomaker(deco_args)(foo)
@deco1(deco_arg)
@deco2
def func():pass
=>func=deco1(deco_arg)(deco2(func))

AOP(Aspect Oriented Programming,面向方面编程)

  • 引入日志
  • 增加计时逻辑来检测性能
  • 给函数加入事务的能力
  • 时戳装饰/时戳服务器
  • 在装饰器中置入通用功能的代码来降低程序复杂度。

4、传递函数
Python中函数就像其他对象,函数可以被引用(访问或者以其它变量作为其别名),也可以作为参数传入函数,以及可以作为列表和字典等容器对象的元素。函数同其他对象区别开来的特征是函数可以调用。

5、Formal Arguments(形参)
Python函数的形参集合包括所有必要参数、关键字参数和所有默认值。
(1)位置参数
无论何时调用函数,都必须提供函数的所有位置参数。可以不按位置地将关键字参数传入函数,给出关键字来匹配其在参数列表中的合适的位置是被准予的。
(2)默认参数
所有位置参数必须出现在任何一个默认参数之前。

6、可变长度的参数
(1)非关键字可变长参数(元组)
使用*符号来指定元组。
可变长的参数元组必须在位置参数和默认参数之后。
(2)关键字变量参数(字典)
使用**符号来指定字典。
1.6之前,变长对象只能通过apply()函数传递给被调用函数。

7、函数式编程
(1)匿名函数与lambda表达式

lambda [arg1 [,arg2,...,argN]]:expression

Python允许用lambda关键字创造匿名函数。
一个完整的lambda语句代表了一个表达式,这个表达式的定义体必须和声明放在同一行。

def true():return True <=>lambda:True
def add(x,y):return x+y <=>lambda x,y:x+y
def usuallyAdd2(x,y=2):return x+y <=>lambda:x,y=2:x+y(支持默认参数)
def showAllAsTuple(*z):return z <=>lambda *z:z(支持可变参数)

(2)内建函数
①apply()
apply(func[,nkw][,kw])未来版本中会消失。
②filter()过滤器函数
filter(func,seq)给定一个对象的序列和一个“过滤”函数,每个序列元素都通过这个过滤器进行筛选,保留函数返回为真的对象。
③map()
map(func,seq1[,seq2…])
map()将函数调用“映射”到每个序列的元素上,并返回一个含有所有返回值的列表。

map(None,[1,3,5],[2,4,6])=>[(1,2),(3,4),(5,6)]
zip([1,3,5],[2,4,6])=>[(1,2),(3,4),(5,6)]

④reduce()
reduce(func,seq[,init])
reduce使用一个二元函数,一个序列和一个可选的初始化器,卓有成效地将那个列表的内容“减少”为一个单一的值。(“折叠”)

reduce(func,[1,2,3])≡func(func(1,2),3)

(3)偏函数应用(2.5)
functools模块
currying概念:一个带n个参数,curried的函数固化第一个参数为固定参数,并返回另一个带有n-1个参数的函数对象。
分别类似于LISP的原始函数car和cdr的行为。currying能泛化成为偏函数应用(partial function application,PFA)这种函数将任意数量(顺序)的参数的函数转化成另一个带剩余参数的函数对象。

add1=partial(add,1)=>add1(x)==add(1,x)
mul100=partial(mul,100)=>mul100(x)==mul(100,x)

使用带关键字参数的PFA。

baseTwo=partial(int,base=2)=>baseTwo('10010')==int('10010',base=2)(关键字参数总是出现在形参之后)

PFA优秀应用:提供“部分GUI模块化”(部分类实例化)

8、变量作用域
(1)全局变量与局部变量
搜索标识符的顺序:先从局部作用域开始,再到全局域。未找到,抛出NameError异常。
(2)global语句
局部变量会覆盖同名的全局变量。
明确地引用一个已命名的全局变量,必须使用global语句。

global var1[,var2][,...varN]

(3)作用域的数字
2.1之前,虽然存在多个函数的嵌套,但不能访问超过两个作用域:一个函数的局部作用域和全局作用域。
(4)闭包
Python的静态嵌套域。内部函数。
在一个内部函数里,对在外部作用域(但不是在全局作用域)的变量进行引用,那么内部函数就被称为闭包(closure)。定义在外部函数内的但由内部函数引用或者使用的变量被称为自由变量。闭包也是函数,但它们能携带一些额外的作用域。(”流浪”的作用域,不属于全局名称空间域或者局部的)闭包对于安装计算、隐藏状态和在函数对象和作用域中随意地切换是很有用的。闭包在GUI或者很多API支持回调函数的事件驱动编程中也很有些用处。闭包更适合需要一个必需有自己作用域的回调函数的情况。
使用函数的func_closure属性来追踪自由变量。
(5)作用域和lambda
一个lambda表达式定义一个只有它自己才能访问的局部作用域。

9、生成器
生成器的动机:在迭代中以某种方式生成下一个值并且返回;协同程序(协同程序是可以运行的独立函数调用,可以暂停或者挂起,并从程序离开的地方继续或者重新开始。)
挂起返回出中间值并多次继续的协同程序被称为生成器。2.2中加入生成器,2.3成为标准,2.5得到提高。
生成器是一个带yield语句的函数,生成器通过yield语句可以暂停并返回一个中间的结果。当达到一个真正的返回或者函数结束没有更多的值返回,一个StopIteration异常就会被抛出。

10、其他
Python不支持函数重载,所以需要使用type()这个内建函数作为代理,来处理有着不同参数类型的函数的多重声明以模拟类C语言的函数重载。
Python支持静态地嵌套域(在2.1中引入并在2.2时成为标准),使得内部函数很有用。这之前的版本中,内部函数没什么意义,因为那些版本只支持全局和一个局部域。

你可能感兴趣的:(Python,Python函数,函数式编程,Python闭包,lambda表达式,Python)