Python学习笔记(七):高级特性、函数式编程、模板(快速入门篇)

来源:互联网 发布:燕十八php视频教程 编辑:程序博客网 时间:2024/05/16 12:26

看完自强学堂的介绍后,觉得少讲了很多在《Head First Python》和《Python基础教程》中有的东西,于是借廖雪峰的博客进行进一步补充:http://www.liaoxuefeng.com/wiki/001374738125095c955c1e6d8bb493182103fac9270762a000

由于是补充,所以这里仅提及在前面笔记中缺少的东西,不做重复介绍。

高级特性

列表生成式

运用列表生成式,可以快速生成list,可以通过一个list推导出另一个list,而代码却十分简洁。

[x * x for x in range(1, 11) if x % 2 == 0]Result:[4, 16, 36, 64, 100]

生成器

generator是非常强大的工具,在Python中,可以简单地把列表生成式改成generator,也可以通过函数实现复杂逻辑的generator。

要理解generator的工作原理,它是在for循环的过程中不断计算出下一个元素,并在适当的条件结束for循环。对于函数改成的generator来说,遇到return语句或者执行到函数体最后一行语句,就是结束generator的指令,for循环随之结束。

列表生成式改生成器

只要把一个列表生成式的[]改成(),就创建了一个generator

L = [x * x for x in range(10)] #列表生成式
g = (x * x for x in range(10)) #生成器

创建了一个generator后,基本上永远不会调用next()方法,而是通过for循环来迭代它。

yield关键字的生成器

如果推算的算法比较复杂,用类似列表生成式的for循环无法实现的时候,还可以用函数来实现。

def fib(max):    n, a, b = 0, 0, 1    while n < max:        yield b         #print b        a, b = b, a + b        n = n + 1

函数是顺序执行,遇到return语句或者最后一行函数语句就返回。而变成generator的函数,在每次调用next()的时候执行,遇到yield语句返回,再次执行时从上次返回的yield语句处继续执行。

函数式编程

高阶函数

把函数作为参数传入,这样的函数称为高阶函数,函数式编程就是指这种高度抽象的编程范式。

  • 变量可以指向函数

    >>> f = abs>>> f(-10)
  • 函数名也是变量

    >>> abs = 10>>> abs(-10)Traceback (most recent call last):  File "<stdin>", line 1, in <module>TypeError: 'int' object is not callable

注:由于abs函数实际上是定义在–builtin–模块中的,所以要让修改abs变量的指向在其它模块也生效,要用–builtin–.abs = 10。

map/reduce

map()函数接收两个参数,一个是函数,一个是序列,map将传入的函数依次作用到序列的每个元素,并把结果作为新的list返回。

>>> map(str, [1, 2, 3, 4, 5, 6, 7, 8, 9])['1', '2', '3', '4', '5', '6', '7', '8', '9']

reduce把一个函数作用在一个序列[x1, x2, x3…]上,这个函数必须接收两个参数,reduce把结果继续和序列的下一个元素做累积计算,其效果就是:

reduce(f, [x1, x2, x3, x4]) = f(f(f(x1, x2), x3), x4)

filter

Python内建的filter()函数用于过滤序列。

和map()类似,filter()也接收一个函数和一个序列。和map()不同的时,filter()把传入的函数依次作用于每个元素,然后根据返回值是True还是False决定保留还是丢弃该元素。

def is_odd(n):    return n % 2 == 1filter(is_odd, [1, 2, 4, 5, 6, 9, 10, 15])  # 结果: [1, 5, 9, 15]

返回函数

函数作为返回值

def lazy_sum(*args):    def sum():        ax = 0        for n in args:            ax = ax + n        return ax    return sum>>> f = lazy_sum(1, 3, 5, 7, 9)  #调用lazy_sum()时,返回的并不是求和结果,而是求和函数>>> f()  #调用函数f时,才真正计算求和的结果

在这个例子中,我们在函数lazy_sum中又定义了函数sum,并且,内部函数sum可以引用外部函数lazy_sum的参数和局部变量,当lazy_sum返回函数sum时,相关参数和变量都保存在返回的函数中,这种称为“闭包(Closure)”的程序结构拥有极大的威力。

请再注意一点,当我们调用lazy_sum()时,每次调用都会返回一个新的函数,即使传入相同的参数

闭包

返回闭包时牢记的一点就是:返回函数不要引用任何循环变量,或者后续会发生变化的变量。

如果一定要引用循环变量怎么办?方法是再创建一个函数,用该函数的参数绑定循环变量当前的值,无论该循环变量后续如何更改,已绑定到函数参数的值不变。缺点是代码较长,可利用lambda函数缩短代码。

匿名函数(lambda)

>>> map(lambda x: x * x, [1, 2, 3, 4, 5, 6, 7, 8, 9])匿名函数lambda x: x * x实际上就是:def f(x):    return x * x

关键字lambda表示匿名函数,冒号前面的x表示函数参数。

匿名函数有个限制,就是只能有一个表达式,不用写return,返回值就是该表达式的结果。

用匿名函数有个好处,因为函数没有名字,不必担心函数名冲突。此外,匿名函数也是一个函数对象,也可以把匿名函数赋值给一个变量,再利用变量来调用该函数

装饰器

OOP的装饰模式需要通过继承和组合来实现,而Python除了能支持OOP的decorator外,直接从语法层次支持decorator。Python的decorator可以用函数实现,也可以用类实现。

decorator可以增强函数的功能,定义起来虽然有点复杂,但使用起来非常灵活和方便。

一个完整的decorator的写法如下:

import functoolsdef log(func):    @functools.wraps(func)  #把原始函数的__name__等属性复制到wrapper()函数中,否则,有些依赖函数签名的代码执行就会出错    def wrapper(*args, **kw):   #wrapper()函数可以接受任意参数的调用        print 'call %s():' % func.__name__  #函数对象有一个__name__属性,可以拿到函数的名字        return func(*args, **kw)    #func的__name__已经从原来的'func'变成了'wrapper'    return wrapper

或者针对带参数的decorator:

import functoolsdef log(text):    def decorator(func):        @functools.wraps(func)        def wrapper(*args, **kw):            print '%s %s():' % (text, func.__name__)            return func(*args, **kw)        return wrapper    return decorator

定义:

@log('execute') #相当于log('execute')(now)def now():    print '2013-12-25'

偏函数

当函数的参数个数太多,需要简化时,使用functools.partial可以创建一个新的函数,这个新函数可以固定住原函数的部分参数,从而在调用时更简单。

>>> import functools>>> int2 = functools.partial(int, base=2)

模板

使用模板

运行测试

if __name__=='__main__':    test()

当我们在命令行运行模块文件时,Python解释器把一个特殊变量–name–置为–main–,而如果在其他地方导入该模块时,if判断将失败,因此,这种if测试可以让一个模块通过命令行运行时执行一些额外的代码,最常见的就是运行测试。

作用域

在一个模块中,我们可能会定义很多函数和变量,但有的函数和变量我们希望给别人使用,有的函数和变量我们希望仅仅在模块内部使用。在Python中,是通过_前缀来实现的。

正常的函数和变量名是公开的(public),可以被直接引用,比如:abc,x123,PI等;

类似–xxx–这样的变量是特殊变量,可以被直接引用,但是有特殊用途,比如上面的–author–,–name–就是特殊变量,模块定义的文档注释也可以用特殊变量–doc–访问,我们自己的变量一般不要用这种变量名;

类似-xxx和–xxx这样的函数或变量就是非公开的(private),不应该被直接引用,比如-abc,–abc等;

之所以我们说,private函数和变量“不应该”被直接引用,而不是“不能”被直接引用,是因为Python并没有一种方法可以完全限制访问private函数或变量,但是,从编程习惯上不应该引用private函数或变量。

使用_future_

Python提供了–future–模块,把下一个新版本的特性导入到当前版本,于是我们就可以在当前版本中测试一些新版本的特性。

0 0
原创粉丝点击