python高级特性的学习

Python的学习

高级特性

切片

迭代

列表生产式

L=[]
for x in range(1,11):
    L.append(x*x)

但是循环太繁琐,而列表生成式则可以用一行语句代替生成上面的list:

[x*x for x in range(1,11)]

for循环后面还可以加上if判断,这样我们就可以筛选出仅偶数的平方:

[x*x for x in range(1,11) if x%2==0]

还可以使用两层循环,可以生成全排列

[m+n for m in ‘ABC’ for n in ‘XYZ’]
result:
[‘AX’,’AY’,’AZ’,’BX’,’BY’,’BZ’,’CX’,’CY’,’CZ’]

运用列表生成器,可以写出非常简洁的代码

import os
[d for d in os.listdir(‘.’)]
[‘.emacs.d’,‘.ssh’,...]

for循环其实可以同时使用两个甚至多个变量

for k,v in d.items():
    print(k,’=’,v)

裂变生成式也可以使用两个变量来生产list:

[k+’=‘+v for k,v in d.items()]

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

生成器

通过列表生成器,我们可以直接创建一个list。但是,受限于内存,列表容量肯定是有限的。然而,创建一个100万的元素的列表,不仅需要占用很大的空间。
所以,如果列表元素的可以按照某种算法推算出来,那我们是否可以在循环的过程中不断推算出后续的元素?这样我们就不需要大量的内存空间,从而节省了大量的内存空间。
在python中,一遍推导一遍计算的机制,称为生成器。generator

要创建一个generator,有很多种方法。第一种方法很简单,只要把列表生成器[]改成().就可以创建一个generator。

L=[x*x for x in range(10)]

g=(x*x for x in range(10))

创建L和g区别仅在于最外面层的【】和(),【】是一个列表,然而()则是一个generator。

可以通过next()函数来获得下一个返回值。

斐波拉契列用列

def fib(max):
    n,a,b=0,0,1
    while n<max:
        print b
        a,b=b,a+b
        n=n+1
    return ‘done’   

仔细观察,可以看出,fib函数实际上是定义了斐波拉契数列的推算规则,可以从第一个元素开始,推算出后续任意的元素,这种逻辑其实非常类似generator。

def fib(max):
    n,a,b=0,0,1
    while n<max:
        yield n
        a,b=b,a+b
        n=n+1
    return ‘done’       

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

举一个简单的例子,定义一个gener,依次返回数字1,3,5:

def odd():
    print(‘step 1’)
    yield 1
    print(’step 2’)
    yield 3
    print(’step 3’)
    yield 5

调用该generator时,首先要生成一个generator对象,然后用next()函数不断获得下一个返回值:

o=odd()
next(o)
next(o)
next(o)

可以看到,odd不是普通函数,而是generator,在执行过程中,遇到yield就终端,下次有继续执行。执行3次yield后,已经没有yield可以执行了,所以,第4次调用next(o)就报错,

但是用for循环调用generator时,发现拿不到generator的return语句的返回值。如果想要拿到返回值,必须捕获stopIteration错误,返回值包含在StopIterationd的value中:

while True:
    try:
        x=next(g)
        print(‘g:’,x)
    exception StopInteration as e:
        break

迭代器

我们已经知道,可以直接作用域for循环的数据了下有以下几种:
一类是集合数据类:

  • 一类是集合数据类型,如list、tuple、dict、set、str等
  • 一类是generator,包括生成器和带yield的generator function
    这些可以直接作用于for循环的对象统称为可迭代对象:Iterable。
    可以使用isinstance()判断一个对象是否是Iterable对象
from collections import Iterable
isinstance([],Iterable)

而生产器不但可以作用于for循环,还可以被next()函数不断调用并返回下一个值,直到最后抛出StopIteration错误表示无法继续返回下一值了。
可以被next()函数调用并不断返回下一个值的对象陈给迭代器:Iterator.

isinstance(iter([]),Iterator)

函数式编程

高阶函数

map/reduce

python内建了map()和reduce()函数
我们先看map。map()函数接收两个参数,一个是函数,一个是iterable,map将闯入的函数依次作用到序列的每个元素,并把结果作为新的Iterator返回。
map()传入的第一个参数是f,即函数对象本身。由于结果r是一个Iterator是惰性序列。因此通过list()函数让它把整个序列都计算出来并返回一个list。

在看reduce的用法。reduce把一个函数作用一个序列[x1,x2,…],这个函数必须接收两个参数,reduce把结果继续和序列的下一个元素做累积计算。

filter

和map()类似,filter()也接收一个函数和一个序列。和map()不同的是,filter()把传入的函数依次作用于每个元素,然后根据返回值是True和False决定保留还是丢失该元素。
filter的作用是从一个序列中筛选出符合条件的元素。由于filter()使用惰性计算,所以只有在取filter()结果的时候,

sorted

排序也是在程序中经常用到的算法。无论使用冒泡排序还是快速排序,排序的核心是比较两个元素的大小。如果是数字,我们可以直接比较,但是如果是字符串或者两个dict呢?直接比较数字上的大小还是没有意义的,因此,比较的过程必须通过函数抽象出来。

sorted([36,5,-12,9,-21])
sorted([36,5,-12,9,21],key=abs)

默认情况下,对字符串排序,是按照ASCII的大小比较,大写字母Z会排在小写字母a的前面。
现在,我们提出排序应该忽略大小写,按照字母序排序。要实现这个算法,不必对现有代码的大加改动,只要我们能用一个key函数把字符串映射为忽略大小写排序即可。忽略大小写比较两个字符串,实际上就是先把字符串都变成大写或者小写,再比较。

sorted([‘bob’,’about’,’Zoo’,’Credit’])
sorted([‘bob’,’about’,’Zoo’],key=str.lower)
sorted([‘bob’,‘about’,‘Zoo’],key=str.lower,reverse=True)
print(sorted(students,key=itemgetter(0)))
print(sorted(students,key=lambda t:t[1]))
print(sorted(students,key=itemgetter(1),reverse=True)

返回函数

高阶函数除了可以接受函数作为参数外,还可以把函数作为结果返回。

def calc_sum(**args):
    ax=0
    for n in args
        ax=ax+n
    return ax
def lazy_sum(*args):
    def sum():
        ax=0
        for n in args:
            ax=ax+n
        return ax
    return sum      

装饰器

由于函数也是一个对象,而且函数对象可以被赋值给变量,所以,通过变量也能调用该函数。

def now():
    print (‘2005-3-25’)

f=now
f() 

函数对象有一个name属性,可以拿到函数的名字:

now.__name__
f.__name__

现在,假设我们要增强now()函数的功能,比如,在函数调用前后自动打印日志,但又不希望修改now()函数的定义,这种在代码运行期d动态增加的功能的方式,称之为装饰器。
本质上,decorator就是一个返回函数的高阶函数。所以,我们要定义一个能打印日志的decorator,可以定义如下:

def log(func):  
    def wapper(*args,**kw):
        print(‘call %s():’% func.__name__)
        return func(*args,**kw)
    return wrapper  

观察上面的log,因为它是一个decorator,所以接受一个函数的高阶函数。所以,我们要定义一个能打印日志的decorator,可以定义如下:

@log
def now():
    print(’2015-3-25’)

调用now()函数,不仅会运行now()函数本身,还会运行now()函数前打印一行日志。
把@log放到now()函数的定义出,相当于执行了语句:


                
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值