一.高级特性
1.切片
用来取list或者tuple元素:
L[0:3]; #取得前三 L[:3]; #取得前三 L[-10:]; #取得后十
2.迭代
如果给定一个list或tuple,我们可以通过for循环来遍历这个list或tuple,这种遍历我们称为迭代(Iteration)。
for key in d: #获取所有元素
3.列表生成式
列表生成式即List Comprehensions,是Python内置的非常简单却强大的可以用来创建list的生成式。
>>> [m + n for m in 'ABC' for n in 'XYZ'] #典型的两次循环生成列表 ['AX', 'AY', 'AZ', 'BX', 'BY', 'BZ', 'CX', 'CY', 'CZ']
4.生成器
通过列表生成式,我们可以直接创建一个列表。但是,受到内存限制,列表容量肯定是有限的。而且,创建一个包含100万个元素的列表,不仅占用很大的存储空间,如果我们仅仅需要访问前面几个元素,那后面绝大多数元素占用的空间都白白浪费了。
所以,如果列表元素可以按照某种算法推算出来,那我们是否可以在循环的过程中不断推算出后续的元素呢?这样就不必创建完整的list,从而节省大量的空间。在Python中,这种一边循环一边计算的机制,称为生成器:generator。
要创建一个generator,有很多种方法。第一种方法很简单,只要把一个列表生成式的[]
改成()
,就创建了一个generator:
>>> g = (x * x for x in range(10)) #典型的生成器定义
>>> next(g) 0 >>> next(g) 1 >>> next(g) 4 >>> next(g) 9
自定义生成器,在每次调用
next()
的时候执行,遇到yield
语句返回,再次执行时从上次返回的yield
语句处继续执行。
def odd(): print('step 1') yield 1 print('step 2') yield(3) print('step 3') yield(5) >>> o = odd() >>> next(o) step 1 1 >>> next(o) step 2 3 >>> next(o) step 3 5 >>> next(o) #执行3次yield后,已经没有yield可以执行了,所以,第4次调用next(o)就报错
Traceback (most recent call last): File "<stdin>", line 1, in <module> StopIteration
5.迭代器
列表、元组、字典等可以迭代,但只有元组是迭代对象。生成器(generator)与List之类的集合数据类型同为可迭代对象,但生成器内部储存的是算法,可以由next()函数得到下一次计算的返回值,满足迭代器的特点;而list之类的集合数据类型内部储存的
>>> from collections import Iterable >>> isinstance([], Iterable) True >>> isinstance({}, Iterable) True >>> isinstance('abc', Iterable) True >>> isinstance((x for x in range(10)), Iterable) True >>> isinstance(100, Iterable) False >>> from collections import Iterator >>> isinstance((x for x in range(10)), Iterator) True >>> isinstance([], Iterator) False >>> isinstance({}, Iterator) False >>> isinstance('abc', Iterator) False
二.函数式编程
1.高阶函数
(1)map/reduce
map
map()传入的第一个参数是f,即函数对象本身。由于结果r是一个Iterator,Iterator是惰性序列,因此通过list()函数让它把整个序列都计算出来并返回一个list。
>>> def f(x): ... return x * x ... >>> r = map(f, [1, 2, 3, 4, 5, 6, 7, 8, 9]) >>> list(r) [1, 4, 9, 16, 25, 36, 49, 64, 81]
典型的map()生成列表:
>>> list(map(str, [1, 2, 3, 4, 5, 6, 7, 8, 9])) ['1', '2', '3', '4', '5', '6', '7', '8', '9']
reduce
reduce把一个函数作用在一个序列[x1, x2, x3, ...]上,这个函数必须接收两个参数,reduce把结果继续和序列的下一个元素做累积计算,其效果就是:
>>> from functools import reduce >>> def fn(x, y): ... return x * 10 + y ... >>> reduce(fn, [1, 3, 5, 7, 9]) 13579总结:map单独处理每一个结果,reduce把前一次处理的结果与下一次参数一起进行再次运算。
(2)filter
和map()类似,filter()也接收一个函数和一个序列。和map()不同的是,filter()把传入的函数依次作用于每个元素,然后根据返回值是True还是False决定保留还是丢弃该元素。
def not_empty(s): return s and s.strip() list(filter(not_empty, ['A', '', 'B', None, 'C', ' '])) #可见本质上filter是个筛选函数 # 结果: ['A', 'B', 'C']
(3)sorted
Python内置的sorted()函数就可以对list进行排序:
>>> sorted([36, 5, -12, 9, -21]) [-21, -12, 5, 9, 36]
可以给sorted的key参数进行修改,按照成绩排序:
L = [('Bob', 75), ('Adam', 92), ('Bart', 66), ('Lisa', 88)] def by_name(t): return t[0] L2 = sorted(L, key=by_name) print(L2)
2.返回函数与闭包
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) >>> f <function lazy_sum.<locals>.sum at 0x101c6ed90> >>> f() 25
在这个例子中,我们在函数lazy_sum中又定义了函数sum,并且,内部函数sum可以引用外部函数lazy_sum的参数和局部变量,当lazy_sum返回函数sum时,相关参数和变量都保存在返回的函数中,这种称为“闭包(Closure)”的程序结构拥有极大的威力。
3.匿名函数
>>> list(map(lambda x: x * x, [1, 2, 3, 4, 5, 6, 7, 8, 9])) [1, 4, 9, 16, 25, 36, 49, 64, 81]
通过对比可以看出,匿名函数lambda x: x * x实际上就是:
def f(x): return x * x
关键字lambda表示匿名函数,冒号前面的x表示函数参数。
4.装饰器
一个典型的装饰器:
def log(func): def wrapper(*args, **kw): #参数定义是(*args, **kw),因此,wrapper()函数可以接受任意参数的调用
print('call %s():' % func.__name__) return func(*args, **kw) return wrapper
@log def now(): print('2015-3-25') >>> now() call now(): 2015-3-25
假设我们要增强now()函数的功能,比如,在函数调用前后自动打印日志,但又不希望修改now()函数的定义,这种在代码运行期间动态增加功能的方式,称之为“装饰器”(Decorator)。(这里就不展示多层嵌套的例子)
5.偏函数
当函数的参数个数太多,需要简化时,使用functools.partial可以创建一个新的函数,这个新函数可以固定住原函数的部分参数,从而在调用时更简单。
>>> import functools
>>> int2 = functools.partial(int, base=2) #构造一个简单的函数
>>> int2('1000000')
64
>>> int2('1010101')
85
参考网站:廖雪峰的官方网站