Python 学习#7 函数与函数式编程

在此前章节我们已经引入了函数这个概念,并介绍了函数的创建与调用。除了已经提到的特性以外,python中的函数还支持多种调用方式以及参数类型并实现了一些函数式编程的接口。本章将重点了解函数的创建、调用,内嵌函数和函数装饰器,特殊函数参数的定义和调用方式,lambda创建需要的匿名函数以及python中的作用域机制。

函数

什么是函数

函数是对程序进行结构化或过程化的一种编程方法。能将整块代码巧妙地隔离成易于管理的小块,避免代码重复。

函数会向调用者返回一个值或不返回,返回值可以是一个值或对象。当没有显式的返回元素时,python会默认返回None。如果函数返回多个对象,python实际将是把他们放在一个元组中一起返回。

函数的调用

同其他语言一样,python中函数的调用也是通过一对圆括号来进行。

函数的参数也与C/C++中函数参数没有太大区别。在允许参数缺失时,可以使用默认参数的方式,例如foo(x=0)。

函数的创建

函数是通过def语句来创建的。

def hello(name):
	'return hello name'
	return "hello"+str(name)

与其他高级语言类似,python也不允许在函数未声明之前就对其进行引用或调用。
函数的文档子串可以通过hello._doc_或者help()函数来调用。

内嵌函数

在函数体内创建另一个函数(对象)是完全合法的,这种函数叫做内嵌函数(有些类似js)。例如:

def foo():
    def bar():
        print("is bar")
    print("is foo")
    bar()
    
if __name__ == '__main__':
    foo()

但要注意的是内嵌函数的作用域,在没有任何外部引用的情况下,出了在函数体内,任何地方都不能对齐进行调用。
内嵌函数是函数的函数,所以称为子函数,而其外部的函数称为母函数。
闭包:是一种满足特殊情况的内嵌函数,在子函数中有对母函数某些变量进行引用,那么这个子函数称为闭包。但当母函数和子函数都有对变量的定义、赋值,并且母函数外是无法调用子函数的,所以需要在母函数的返回值中将子函数返回以实现对子函数的调用。
需要知道的一点是,在python中“一切皆对象”,函数也是如此,所以在母函数中返回子函数,实际是返回了子函数的对象

# 闭包与子函数的调用
def foo(a,b):
    def bar(x):
        print(a*x+b)
    return bar
if __name__ == '__main__':
    func=foo(2,2)
    func(4)	#10
*函数(与方法)装饰器

在讨论装饰器之前,必须先明白闭包到底有什么用?
通过之前闭包的距离可以知道:

  • 闭包必须返回函数对象
  • 闭包所返回的函数必须引用外部变量(不是全局变量)。

python中函数的作用域由def来决定,有些类似C++中花括号的作用。上面的例子实现的功能是,通过第一层函数即ab确定了一条直线的函数,将函数对象赋给func,之后func调用第二层函数来求出指定x值的y。
而在不使用嵌套函数的情况下,对于每一条直线,都需要创建一个新的函数。

闭包在返回时,所有变量就已经固定,形成了一个封闭的对象,这个对象包含了其引用的所有外部、内部变量和表达式。同时创建对个闭包对象,他们之间的变量将会互相隔离。

装饰器背后的主要动机源自python面向对象编程。装饰器是在函数调用之上的修饰。这些修饰仅是当声明一个函数或者方法的时候,才会应用的额外调用。
修饰器封装一个函数,并且用其他方式来修改它的行为。
装饰器的语法是以@开头,接着是装饰器函数的名字和可选的参数,紧跟着装饰器声明的是被修饰的函数和装饰器的可选参数。例如:

总结来说就是,修饰器是在不改变原函数的基础上,对原函数的功能进行扩展,例如对于除法函数,可以通过修饰保证其除数不为零。
修饰器@实际上就是闭包函数。装饰器所接受的参数一定是函数对象,

# using decorators you can add the extra features in the existing functions
def smart_div(func):
    def inner(a,b):
        if a<b:
            a,b=b,a
        return func(a,b)	#此处返回的参数必须于所修饰的函数数量一致
    return inner

# div1=smart_div(div)
@smart_div
def div(a,b):
    return print(a/b)
div(2,4)
函数的参数

python函数的形参集合由在调用时要传入函数的所有参数组成,参数与函数声明中的参数列表精确配对。
使用默认参数可以使程序的健壮性上升到极高的级别,特别是在建立接口函数的时候。

可变长的参数:参数组,在指定函数参数列表的时候,可以通过*args,**kwargs来分别指定元素和字典的元素作为参数。例如:

def newfoo(arg1,arg2,*args,**kwargs):
    for i in args:
        print(args)

    for key in kwargs.keys():
        print(key)
        print(kwargs[key])

newfoo(1,2,4,5,6,7, a=1,b=2)
函数式编程

python中允许使用lambda关键字创造匿名函数。匿名是因为不需要以标准的方式来声明,比如说使用def语句。然而作为函数,它依然可以拥有参数。
lambda函数类似于单行的def函数,但需要通过一个变量将其保存。

def func(): return True
t=lambda :True

a=lambda x,y:x+y
print(a(3,5))

filter(func, seq)函数:给定一个序列和一个布尔过滤函数,filter会为列表中每个元素调用给定的布尔函数,将为真的添加到一个列表中。
map(func,seq):map函数类似于filter,不同的是,map是将函数作用在序列的每个元素上,然后返回每次调用返回值的列表。

变量作用域

标识符的作用域是定义其声明在程序离得可应用范围,或者说是我们所说的变量可见性。
定义在函数内的变量有局部作用域,在一个模块中最高级别的变量有全局作用域。

global语句:为了明确的引用一个已命名的全局变量,必须使用global语句。

python中的lambda匿名函数遵循和普通函数一样的作用域规则,一个lambda表达式定义了新的作用域,就像函数定义。

下一章讨论python中的异常机制。第八章

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值