1、迭代器

迭代器是访问数据集合的一种方式,它只能从集合的第一个元素开始顺序访问,直到最后一个元素结束。类似于linux里的cat命令,只能挨行读取文本内容,不可以跳到中间或者尾部读取(不会把所有的数据都读到内存中),对于上G的文件,比较节约内存。该迭代的好处就是它事先不需要准备好集合里的所有元素,遍历到该元素时才会计算处理该元素,这点与列表有很大的不同。

示例1:

a = iter(['add','dfdf','dfdfd'])
print a.next()#取第一个值
print a.next()#取第二个值
print a.next()#取第三个值# a = iter(['add','dfdf','dfdfd'])

迭代器关键字iter(),读取集合元素时,只能使用next()方法挨个读取,每次读取一个值,不能随机读取。

示例2:

for line in open("test.txt").readlines():
  print line

for line in open("test.txt"):   #use file iterators
print line

区别:

for line in open("test.txt").readlines()方法是将整个文件读到内存,然后每行读取;
for line in open("test.txt")方法利用迭代器,每次读取一行。

2、生成器

生成器也是一种迭代器,拥有next()方法并且行为与迭代器完全相同。当一个函数中包含yield关键字时,该函数就是一个生成器函数。这里的yield相当于普通函数里的return,只不过yield返回的是一个生成器。第一次执行next()方法时,才会调用生成器函数。当该函数执行到yied语句时会中止,并以yield的参数作为此次next()方法的返回值返回。之后每次调用next()方法时,生成器函数接着上次中止的yield语句往下继续执行,直到遇到yield语句再此中止。

示例:

def Get_Number():#1#4
yield 0#5#7
yield 1#8#10
yield 2#11#12 a = Get_Number()#
print a.next()#
print a.next()#
print a.next()#

程序第一次执行到print a.next()语句时会调用Get_Number函数,该函数执行到yield 0 时会返回yield后面的参数0,并中止函数的执行。然后程序继续执行第二句print a.next(),继续调用Get_Number函数,然后执行yield 1语句返回1,然后中止函数体的执行,再继续执行第三句print a.next()。。。

示例:单线程并发运算

import time
def consumer(name):
print("%s 准备吃包子啦!" %name)
while True:
baozi = yield print("包子[%s]来了,被[%s]吃了!" %(baozi,name)) def producer(name):
c = consumer('A')
c2 = consumer('B')
c.__next__()
c2.__next__()
print("老子开始准备做包子啦!")
for i in range(10):
time.sleep(1)
print("做了2个包子!")
c.send(i)
c2.send(i) producer("ahaii")

3、装饰器

详细示例,参照银角大王博客:http://www.cnblogs.com/wupeiqi/articles/4980620.html

示例1:

需求: 在调用tv()函数时,需要添加一个登录验证的环节,且不能修改tv()函数内部的代码。

def login(func):
print 'login'
return func#只返回func函数的内存地址,不调用func def tv(name):
print '%s to tvpage' % name f = login(tv)
f('ahaii')

示例中,login()函数返回func参数,该参数只是一个函数的内存地址。执行 f = login(tv)时,将tv作为参数传给login(),然后执行login()函数内部代码(登录验证模块)。执行完成后返回tv函数在内存的位置,此时 f = tv。当执行f('ahaii')时,即tv('ahaii'),调用tv()函数,执行该函数代码。

示例2:

def login(func):
def inner(arg):#执行tv('ahaii')语句时第二次调用的tv
print '验证'
return func(arg)#第一次调用的tv
return inner @login
#装饰器,调用login函数,并以被装饰的函数(tv)的函数名为参数,即login(tv),效果如下:
# def login(tv):
# def inner(arg):
# print '验证'
# return tv(arg)
def tv(name):
print '%s to tvpage' tv('ahaii')#调用inner()函数

上例中,@login语句即为装饰器,该语句下面的tv()函数就是被装饰的函数。该程序执行流程是:1、def login(func):,将该函数加载到内存,不执行。2、@login。

@login背后的故事:

.1 当程序执行到@login语句时,会把@login装饰的函数(即该语句下面的函数tv())当作参数传递给login()函数,此时会执行login(tv)。

.2 login(tv),执行内部语句def inner(arg) 和 return inner,因没有调用inner()函数,所以函数体 print '验证' 和return func(arg) 不会被执行。该句的执行结果是inner函数体。

.3 将第2步执行的返回值赋值给被login修饰的函数,即将inner函数体赋值给tv()函数。

即 新tv=def inner(arg):

    print ...

    return func(arg) #返回原来的tv

执行 tv('ahaii') 时,会将 'ahaii'参数传给inner()函数。

综上,装饰器的功能就是,当执行tv()函数时,需要先执行另外一个新的tv()函数,在新的tv()函数里可以添加新的功能模块(执行tv函数之前,先执行新的tv函数( inner函数))。比如登录验证,然后再执行原来的tv()函数。这样,即未改动原来的tv()函数,又添加了新功能。

4、递归

示例1:

def calc(n):
print n
if n/2 >1:
res = calc(n/2)
print res
print n
return n calc(10)

将函数执行的结果作为参数再传递给函数本身。

示例2 斐波那契数列:

def func(arg1,arg2,stop):
arg3 = arg1 + arg2
if arg1 == 0:
print arg1,arg2
print arg3
if arg3 < stop:
func(arg2,arg3,stop) func(0,1,50)

示例3 找有序数列中某一值:

def find(List,Number):
mid = len(List)/2#取中间值
if len(List)>=1:
if List[mid] >Number:
print 'in the left %s' % List[mid]
find(List[:mid],Number)#切片,取列表左半
elif List[mid] <Number:
print 'in the right %s' % List[mid]
find(List[mid:],Number)
else:
print 'find the number,,, %s' % Number
else:
print 'cannot find the number,,,' find(range(1,100000),9)

思路:先取有序数列的中间值与要查找的值x比较大小,若大于x,则说明x在该中间值的左边。利用切片取数列左半部门,然后递归继续查找中间值与x比较。

5、算法

示例 二维列表90度旋转:

array=[[col for col in range(5)] for row in range(5)] #初始化一个4*4数组
#array=[[col for col in 'abcde'] for row in range(5)] for row in array: #旋转前先看看数组长啥样
print(row) print('-------------')
for i,row in enumerate(array): for index in range(i,len(row)):
tmp = array[index][i] #get each rows' data by column's index
array[index][i] = array[i][index] #
array[i][index] = tmp
for r in array:print r print('--one big loop --')

6、正则表达式

匹配格式

模式描述
^匹配字符串的开头
$匹配字符串的末尾。
.匹配任意字符,除了换行符,当re.DOTALL标记被指定时,则可以匹配包括换行符的任意字符。
[...]用来表示一组字符,单独列出:[amk] 匹配 'a','m'或'k'
[^...]不在[]中的字符:[^abc] 匹配除了a,b,c之外的字符。
re*匹配0个或多个的表达式。
re+匹配1个或多个的表达式。
re?匹配0个或1个由前面的正则表达式定义的片段,非贪婪方式
re{ n} 
re{ n,}精确匹配n个前面表达式。
re{ n, m}匹配 n 到 m 次由前面的正则表达式定义的片段,贪婪方式
a| b匹配a或b
(re)G匹配括号内的表达式,也表示一个组
(?imx)正则表达式包含三种可选标志:i, m, 或 x 。只影响括号中的区域。
(?-imx)正则表达式关闭 i, m, 或 x 可选标志。只影响括号中的区域。
(?: re)类似 (...), 但是不表示一个组
(?imx: re)在括号中使用i, m, 或 x 可选标志
(?-imx: re)在括号中不使用i, m, 或 x 可选标志
(?#...)注释.
(?= re)前向肯定界定符。如果所含正则表达式,以 ... 表示,在当前位置成功匹配时成功,否则失败。但一旦所含表达式已经尝试,匹配引擎根本没有提高;模式的剩余部分还要尝试界定符的右边。
(?! re)前向否定界定符。与肯定界定符相反;当所含表达式不能在字符串当前位置匹配时成功
(?> re)匹配的独立模式,省去回溯。
\w匹配字母数字
\W匹配非字母数字
\s匹配任意空白字符,等价于 [\t\n\r\f].
\S匹配任意非空字符
\d匹配任意数字,等价于 [0-9].
\D匹配任意非数字
\A匹配字符串开始
\Z匹配字符串结束,如果是存在换行,只匹配到换行前的结束字符串。c
\z匹配字符串结束
\G匹配最后匹配完成的位置。
\b匹配一个单词边界,也就是指单词和空格间的位置。例如, 'er\b' 可以匹配"never" 中的 'er',但不能匹配 "verb" 中的 'er'。
\B匹配非单词边界。'er\B' 能匹配 "verb" 中的 'er',但不能匹配 "never" 中的 'er'。
\n, \t, 等.匹配一个换行符。匹配一个制表符。等
\1...\9匹配第n个分组的子表达式。
\10匹配第n个分组的子表达式,如果它经匹配。否则指的是八进制字符码的表达式。

  

04-21 08:44
查看更多