第七章 函数式编程

7.1又见函数

1.python中的函数式

函数式编程以函数为中心进行代码封装。函数式编程强调了函数的纯粹性。一个纯函数是没有副作用的,即这个函数的运行不会影响其他函数。进程的先后顺序不同会影响最终结果,这被称为竞跑条件,函数式编程消灭了副作用,即无形中消除了竞跑条件的可能。

2.并行运算

所谓的并行运算是指多条指令同时执行。一个程序运行后,就成为一个进程,进程有自己的内存空间,用来储存自身的运行状态、数据和相关代码。一个进程内部又可以有多个称为“线程”的任务,处理器可以在多个线程之间切换,从而形成并行的多线程处理。线程之间可以共享同一个进程的内存空间。

7.2被解放的函数

1.函数作为参数和返回值

def square_sum(a,b):

    return a**2+b**2

def cubic_sum(a,b):

    return a**3+b**3

def argument_demo(f,a,b):

    return f(a,b)

print(argument_demo(square_sum,3,5))

print(argument_demo(cubic_sum,3,5))

2.函数作为返回值

def line_conf():

    def line(x):

        return 2*x+1

    return line

my_line=line_conf()

print(my_line(5))#打印11

我们在line_conf()函数的隶属范围内定义的函数line(),就只能在line_conf()的隶属范围内调用。

3.闭包

def line_conf():

    b=15

    def line(x):

        return 2*x+b#闭包

    b=5

    return line

if __name__=="__main__":

    my_line=line_conf() 

    print(my_line(5))#打印15

line()定义的隶属程序块中引用了高层及的变量b。b的定义并不在line()内部,而是一个外部的对象。我们称b为line()的环境变量。尽管b位于line()定义的外部,但当line被函数line_conf()返回时,还是会带有b的信息。一个函数和他的环境变量组合在一起,就构成了一个闭包。在python中,所谓闭包是一个包含环境变量取值的函数对象。

闭包可以提升代码的复用性:

def line_conf(a,b):

    def line(x):

        return a*x+b

    return line

line1=line_conf(1,1)

line2=line_conf(-2,-6)

这个例子中,函数line()与环境变量a、b构成闭包。除了复用代码,闭包还能起到减少函数参数的作用。

7.3小女子的化妆匣

1.装饰器

装饰器可以对一个函数、方法或者类进行加工。

def decorator_demo(old_function):

    def new_function(a,b):

        print("input",a,b)

        return old_function(a,b)

    return new_function

@decorator_demo

def square_sum(a,b):

    return a**2+b**2

if __name__=="__main__":

    print(square_sum(3,4))

定义好装饰器后,我们就可以通过@语法使用了,在函数square_sum()定义之前调用@decorator_demo,实际上是将square_sum()传递给了decorator_demo(),并将decorator_demo()返回的新函数对象赋给原来的函数名square_sum()。

2.带参装饰器

def pre_str(pre=""):

    def decorator(old_function):

        def new_function(a,b):

             print(pre+"input",a,b)

             return old_function(a,b)

        return new_function

    return decorator

@pre_str("^_^")

def square_sum(a,b):

    return a**2+b**2

if __name__ =="__main__":

    print(square_sum(3,4))

3.装饰类

一个装饰器可以接受一个类,并返回一个类,从而起到加工类的效果P180。

7.4高阶函数

1.lambda与map

能接收其他函数作为参数的函数,被称为高阶函数。

lambda:

lambda_sum=lambda x,y:x+y

print(lambda_sum(3,4))

map:

data_list=[1,3,5,6]

result=map(lambda x:x+3,data_list)

map的第一个参数是一个函数对象,第二个参数是一个可循环对象。对于data_list的每个元素,lamdba函数都会调用一次。那个元素会成为lamdba函数的参数。最终,map()会返回一个迭代器。迭代器中的元素,就是多次调用lamdba函数的结果。

这个函数也可以是一个多参数的函数,这时map()的参数列表中就需要提供相应数目的课循环对象。

2.filter函数

如果函数对象返回的是True,则该次的元素被放到返回的迭代器中。

def larger100(a):

    if a>100:

        return True

    else:

        return False

for itemin filter(larger100,[10,56,101,500]):

    print(item)

3.reduce函数

reduce()在标准库中的functools包中,使用之前需要引入。reduce()对作为参数的函数对象有一个特殊要求,就是这个作为参数的函数必须能接收两个参数:

from functoolsimport reduce

data_list=[1,2,5,7,9]

result=reduce(lambda x,y:x+y,data_list)

print(result)#打印24

函数reduce()的第一个参数是求和sum()函数,它接收两个参数x和y。上一次运算的结果将作为下一次调用的第一个参数。

4.并行处理

下载的程序就是在多进程条件下使用了多线程的map()方法。这段进程多线程的下载同一个URL下的资源。程序用了第三方包requests来进行HTTP下载P187。从结果可以看到,运行时间能大为缩短。

7.5自上而下

1.便捷表达式

生成器表达式是构建生成器的便捷方法:

gen=(x for x in range(4))

生成表的快捷方式,列表解析:
l=[x**2 for x in range(10)]

除了for,列表解析中还可以使用if:

xl=[1,3,5]

yl=[9,12,13]

l=[x**2 for (x,y)in zip(xl,yl)if y>10]

2.懒惰求值

介绍迭代器时提到过,迭代器的元素是实时计算出来的。在使用该元素之前,元素并不会占据内存空间。与之相对应,列表在建立时,就已经产生了各个元素的值,并保存在内存中。迭代器的工作方式正是函数式编程中的懒惰求值。我们可以对迭代器进行各种各样的操作,但只有在需要时,迭代器才会计算出具体的值。如,,列表提前准备数据的方式,就浪费了很多运算资源。

3.itertools包

这个包提供了更加灵活的生成迭代器的工具,这些工具的输入大都是已有的迭代器。P193

你可能感兴趣的:(第七章 函数式编程)