一、高级特性
1.切片
取前3个元素用L[0:3]表示,从索引0开始取,直到索引3为止,但不包括索引3。如果第一个索引是0可省略。前10个数 每两个取一个L[:10:2],所有数 每5个取一个L[::5],原样复制[:]
Python没有针对字符串的截取函数,只需要切片一个操作就可以完成,非常简单。
2.迭代
在Python中,迭代是通过for ... in来完成的,而很多语言比如C或者Java,迭代list是通过下标完成的。
如何判断一个对象是可迭代对象呢?方法是通过collections模块的Iterable类型判断
>>> from collections import Iterable
>>> isinstance('abc', Iterable) # str是否可迭代
True
如果要对list实现类似Java那样的下标循环怎么办?Python内置的enumerate函数可以把一个list变成索引-元素对,这样就可以在for循环中同时迭代索引和元素本身
>>> for i, value in enumerate(['A', 'B', 'C']):
... print i, value
3.列表生成式
要生成list [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]可以用range(1, 11)
要生成[1x1, 2x2, 3x3, ..., 10x10]可以用[x * x for x in range(1, 11)]
筛选出仅偶数的平方 [x * x for x in range(1, 11) if x % 2 == 0]
使用两层循环,可以生成全排列>>> [m + n for m in 'ABC' for n in 'XYZ'] 结果: ['AX', 'AY', 'AZ', 'BX', 'BY', 'BZ', 'CX', 'CY', 'CZ']
for循环其实可以同时使用两个甚至多个变量,比如dict的iteritems()可以同时迭代key和value>>> d = {'x': 'A', 'y': 'B', 'z': 'C' } >>> for k, v in d.iteritems(): ... print k, '=', v
内建的isinstance函数可以判断一个变量是不是字符串>>> isinstance(x, str)
L= [s.lower() if isinstance(s,str) else s for s in L]是condition expression
L= [s.lower() for s in L if isinstance(s,str) else s for s in L]是list comprehension
else 语法不是list comprehension中的,想要用else的话需要用condition expressions。
4.生成器
通过列表生成式,我们可以直接创建一个列表。但是,受到内存限制,列表容量肯定是有限的。而且,创建一个包含100万个元素的列表,不仅占用很大的存储空间,如果我们仅仅需要访问前面几个元素,那后面绝大多数元素占用的空间都白白浪费了。所以,如果列表元素可以按照某种算法推算出来,那我们是否可以在循环的过程中不断推算出后续的元素呢?这样就不必创建完整的list,从而节省大量的空间。在Python中,这种一边循环一边计算的机制,称为生成器(Generator)。
创建一个generator,有很多种方法。第一种方法很简单,只要把一个列表生成式的[]改成(),就创建了一个generator
L = [x * x for x in range(10)]
g = (x * x for x in range(10))
创建L和g的区别仅在于最外层的[]和(),L是一个list,而g是一个generator。
打印出generator的元素,通过generator的next()方法g.next()
generator保存的是算法,每次调用next(),就计算出下一个元素的值,直到计算到最后一个元素,没有更多的元素时,抛出StopIteration的错误。不断调用next()方法实在是太变态了,正确的方法是使用for循环,因为generator也是可迭代对象。
>>> g = (x * x for x in range(10))
>>> for n in g:
... print n
generator的另一种方法。如果一个函数定义中包含yield关键字,那么这个函数就不再是一个普通函数,而是一个generator
斐波那契数列
def fib(max):
n, a, b = 0, 0, 1
while n < max:
yield b
a, b = b, a + b
n = n + 1
二、函数式编程
1.高阶函数:让函数的参数能够接收别的函数。
既然变量可以指向函数,函数的参数能接收变量,那么一个函数就可以接收另一个函数作为参数,这种函数就称之为高阶函数。
1.1 Python内建了map()和reduce()函数。
map()函数接收两个参数,一个是函数,一个是序列,map将传入的函数依次作用到序列的每个元素,并把结果作为新的list返回。
map(str, [1, 2, 3, 4, 5, 6, 7, 8, 9])
reduce这个函数必须接收两个参数,reduce把结果继续和序列的下一个元素做累积计算。
如把一个函数作用在一个序列[x1, x2, x3...]上 reduce(f, [x1, x2, x3, x4]) = f(f(f(x1, x2), x3), x4)
def char2num(s):
return {'0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9}[s]
def str2int(s):
return reduce(lambda x,y: x*10+y, map(char2num, s))
1.2 Python内建的filter()函数用于过滤序列。
和map()类似,filter()也接收一个函数和一个序列。和map()不同的时,filter()把传入的函数依次作用于每个元素,然后根据返回值是True保留,False丢弃该元素。
def isEmpty(s):
return s and s.strip()
print filter(isEmpty,['a','','bb',' ',None])
# 只改成s.strip()时,应该是在内容为None时出错的,因为strip()函数不能作用于None
1.3 Python内置的sorted()函数可以对list进行排序
倒序排print sorted([36, 5, 12, 9, 21], lambda x, y: y - x)
为什么这里是数据在前,函数在后? 因为sorted的函数参数是可选的