四、函数与函数式编程

一、函数
1.1 定义函数

(1) 通过“函数名.__doc__”来访问函数文档字符串,便于日后维护与共享代码

#利用函数求矩形面积
def area_count(L,W):
    area=L*W
    return area

a=input('请输入矩形的长度:')
b=input('请输入矩形的宽度:')
print u'矩形面积为:',area_count(a,b)

1.2 函数调用

(1)可以通过函数名调用,也可以将函数对象赋值给别的变量后,通过该变量名调用,调用时也要加()

(2)参数可以利用参数名=实参的方式指定,如area_count(L=2,W=4)

(3)在python3中调用文件中自己定义的函数,需要使用“from 文件名 import 函数名”进行导入


1.3 内部/内嵌函数

(1)如果一个函数是在另一个函数内部创建的,那么这个函数就叫作内部函数或内嵌函数。定义了内部函数后,整个内部函数都位于外部函数的作用域中,除了外部函数,其他地方都不能对其进行调用。

(2)内部函数也可以使用lambda语句进行定义。

def fout():
    no=23
    def fin():
        ni=10
        return no+ni    #内部函数可以访问外部函数的变量
    print fin()

fout()  #如果直接调用内部函数fin()会出错

二、函数参数
2.1 标准化参数

(1)按照位置传递参数

(2)按照形参名传递参数

(3)默认参数在调用时可以有相应的实参,若没有则取默认值,无默认值的参数必须写在默认参数之前

2.2 可变数量的参数

(1)非关键字可变数量参数(*)

有了非关键字可变数量参数后,调用函数时所有的多余的无关键字指定的实参(匹配标准化参数后剩余的)统统以元组的形式
保存在非关键字可变数量参数中。

def ftuple(arg1,arg2,arg3=333,*arg4):
    print 'arg1=',arg1
    print 'arg2=',arg2
    print 'arg3=',arg3
    print 'the rest args:'
    for eacharg in arg4:
        print eacharg

ftuple(1,2,4,5,6)

(2)关键字可变数量参数(**)

有了关键字可变数量参数后,调用函数时所有的多余的关键字指定的实参统统以字典的形式
保存在关键字可变数量参数中。

def ftuple(arg1,arg2,arg3=333,**arg4):
    print 'arg1=',arg1
    print 'arg2=',arg2
    print 'arg3=',arg3
    print 'the rest args:'
    for eachargkey in arg4:
        print eachargkey,'==>',arg4[eachargkey]

ftuple(1, 2, 4, a=5, c=6)

(3)调用函数时,如果有的实参给定关键字或参数名,有的没有给定,则没有给定的放在实参列表的前面,给定的放在后面。

2.3 函数传递

函数对象作为其它函数的参数

def f(x):
    return x+2
def ff(fun,seq):
    return [fun(eachn) for eachn in seq]

print ff(f,[1,2,3,4,5])

三、装饰器
3.1 无参装饰器
3.2 带参装饰器
四、函数式编程

函数式编程:是一种编程范型,将计算机运算视为数学上的函数计算,并且避免使用程序状态以及易变对象。函数可以接受函数当作输入和输出

python不是函数式编程语言,但吸收了其优点

4.1 lambda表达式

(1)lambda定义了一个匿名函数,所以没有函数名,其结果也不使用return语句返回,表达式与声明放在同一行,参数可选且不需加括号

(2)为了保留并调用这个函数,可以将这个匿名函数赋给一个变量,通过变量来调用函数,也可以将其用作函数参数,通过函数参数来调用

y=lambda L,W:L*W
print y(2,3)

def area(fun,seq1):
    seq=[]
    for (x,y) in seq1:
        seq.append(fun(x,y))
    return seq
#调用时使用Lambda语句创建的函数作为实参
print area(lambda L,W:L*W,[(1,2),(3,4),(5,6)])

4.2 内建函数map、filter、reduce

这三个内建函数都有一个可执行的函数对象参数,可以是lambda创建的,也可以是def定义的函数

(1)map函数

map(函数或lambda表达式,序列1,序列2....)

将函数作用于给定序列的每一个元素,并用一个列表作为返回值;如果给定了多个序列,则map会并行迭代每个序列,每次处理时,map会将每个序列的相应元素组成一个元组,然后将函数或Lambda表达式作用于该元组。

map(lambda x:x*x,[2,3,4,5])
map(lambda x,y:x+y,[1,2,3,4],[3,4,5,6])
#map函数中函数名或lambda表达式为None,则返回一个列表,其功能类似于zip()
map(None,[1,2,3,4],['a','b','c','d'])

(2)filter函数

filter(函数或lambda表达式,序列)

利用函数或lambda表达式对序列中的每个元素进行筛选,保留数值为True的元素序列

#筛选奇数
def odd(n):
    if n%2:
        return True

filter(odd,[1,2,3,4,5,6,7])

filter(lambda n:n%2,[1,2,3,4,5,6,6])

(3)reduce函数

reduce(函数或lambda表达式,序列,[,初始值])

函数或lambda表达式必须是二元函数,如果有初始值,则把初始值和序列第一个元素作为函数参数,求得返回值后再将该值和
序列的第二个元素作为函数参数,依此类推;若没有初始值,则把序列的第一个、第二个元素作为函数参数,依此类推

def mul(x,y):
    return x*y

reduce(mul,[1,2,3,4,5],10)

reduce(lambda x,y:x*y,[1,2,3,4,5,6,7])

4.3 偏函数应用

在使用标准化参数时,如果函数参数过多,可以设置默认参数,降低函数调用的复杂度。但因为函数的应用领域不同,使得不同的调用者可能会希望参数是不同的默认值,这时可以利用functools模块提供的partial函数(偏函数),将带有n个参数的函数,固化一个参数(如果不指定关键字,则固化第一个参数),并返回另一个带有n-1个参数的函数对象。固化参数的值可以根据需要指定。

from functools import partial
def tax(s1,price,number,m):
    if price<m:
        return 0
    else:
        return s1*(price-m)*number
#将s1固化为0.01,
tax1=partial(tax,0.01)
print tax1(20000,5,10000)#等价于tax(0.01,20000,5,10000)
#将m固化为10000
tax2=partial(tax,m=10000)
print tax2(0.01,20000,3)#等价于tax(0.01,20000,3,10000)

 五、变量作用域

变量的作用域分为三个等级:全局(golbal)、局部(local)、外部(nonlocal)。

变量作用域的查找优先级为:局部、外部、全局、内建。其中内建变量是由Python定义的以双下划线开始和结束的变量,如__doc__、__name__等。

5.1 全局变量和局部变量

不在函数内创建的变量就是全局变量。是一个模块中级别最高的变量,能被所有函数访问。

在函数内创建的变量是局部变量,仅在所定义的函数内可见。


5.2 global语句

如果要在函数内改变全局变量的值,需要先在函数体中用global对全局变量进行声明。


5.3 闭包与外部作用域


六、递归

如果一个函数直接或间接调用了自己,那么这个函数就是递归函数。

#求阶乘
def fac(n):
    if n==0 or n==1:
        return 1
    else:
        return fac(n-1)*n

七、生成器

生成器就是一个带有yield语句的函数。生成器能暂停执行并返回一个中间结果,当调用生成器的next方法时,生成器会从刚才暂停的位置继续执行。

#生成器示例
def gen():
    i=1
    yield (u'第%d次返回'%i)
    i=i+1
    yield (u'第%d次返回'%i)
    i=i+1
    yield (u'第%d次返回'%i)

g=gen()
print g.next()#python3中改为print(g.__next__())

猜你喜欢

转载自blog.csdn.net/cc27721/article/details/82456211