Python_4

循环设计

1、range()

利用enumerate()函数,可以在每次循环中同时得到下标和元素:

1
2
3
S = 'abcdefrhijk'
for i in range(0, len(S), 2):
print S[i]

在range函数中,定义了上限、下限、和每次循环的步长

2、enumerate()

1
2
3
4
S = 'abcdefghijk'
for (index,char) in enumerate(S):
print index
print char

enumerate()在每次循环中,返回的是一个包含两个元素的定值表(tuple),两个元素分别赋予index和char。

3、zip()

如果有多个等长的序列,想要每次循环时从各个序列分别取出一个元素,可以利用zip()实现:

1
2
3
4
5
ta = [1,2,3]
tb = [9,8,7]
tc = ['a','b','c']
for (a,b,c) in zip(ta, tb, tc):
print (a,b,c)

zip()函数的功能:从多个列表中,依次各取出一个元素。每次取出的(来自不同列表的)元素合成一个元组,合并成的元组放入zip()返回的列表中。
zip()函数起到了聚合列表的功能。

我们可以分解聚合后的列表:

1
2
3
4
5
6
7
8
9
10
ta = [1,2,3]
tb = [9,8,7]
#聚合
zipped = zip(ta,tb)
print(zipped)
#分解聚合
na,nb = zip(*zipped)
print(na,nb)

循环对象

1、什么是循环对象

循环对象包含一个next()方法,目的是进行到下一个结果。在结束一系列结果之后,举出StopIteration错误。

当一个循环(比如for)调用循环对象时,就会在每次循环时调用next(),直到出现StopIteration,就直到循环已经结束,停止调用next()。

假设我们有一个test.txt的文件:

1234
abcd
efg

运行一下Python:

1
2
3
4
f = open('text.txt')
f.next()
f.next
... #不断输入f.next(),直到最后出现StopIteration

open()返回的实际上是一个循环对象,包含有next()方法。而该next()方法每次返回的就是新的一行的内容,到达文件结尾时举出StopIteration。这样,我们相当于手工进行了循环。

自动进行的话,就是:

1
2
for line in open('test.txt'):
print line

在这里,for结构自动调用next()方法,将该方法的返回值赋予给line。循环直到出现StopIteration的时候结束。

相对于序列,用循环对象的好处在于:不用在循环还没有开始的时候,就生成好要使用的元素。所使用的元素可以在循环过程中逐次生成。这样,节省了空间,提高了效率,编程更灵活。

2、迭代器

从技术上来说,循环对象和for循环调用之间还有一个中间层,就是要将循环对象转换成迭代器(iterator)。这一转换是通过使用iter()函数实现的。

但从逻辑层面上,常常可以忽略这一层,所以循环对象和迭代器常常相互指代对方。

3、生成器

生成器(generator)的主要目的是构成一个用户自定义的循环对象

生成器的编写方法和函数定义类似,只是在return的地方改为yield。生成器中可以有多个yield。当生成器遇到一个yield时,会暂停运行生成器,返回yield后面的值。当再次调用生成器的时候,会从刚才暂停的地方继续运行,直到下一个yield。生成器自身又构成一个循环器,每次循环使用一个yield返回的值。

下面是一个生成器:

1
2
3
4
5
6
def gen():
a = 100
yield a
a = a*8
yield a
yield 1000

该生成器共有三个yield, 如果用作循环器时,会进行三次循环:

1
2
for i in gen():
print i

再考虑如下一个生成器:

1
2
3
def gen():
for i in range(4):
yield i

又可以写成生成器表达式(Generator Expression):

1
G = (x for x in range(4))

4、表推导

普通生成表方法:

1
2
3
L = []
for x in range(10):
L.append(x**2)

表推导方式:

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

与生成器表达式类似,只不过用的是中括号

函数对象

1、lambda函数

普通定义函数方式:

1
2
def func(x, y)
return x + y

用lambda函数的语法定义函数:

1
2
func = lambda x,y: x + y
print func(3.4)

2、函数作为参数传递

1
2
3
4
5
def test(f, a, b)
print 'test'
print f(a,b)
test(func, 3, 5)

可以使用上面的test函数,带入不同的函数参数:

1
test((lambda x,y: x**2 +y), 6, 9)

3、map()函数

1
re = map((lambda x: x+3),[1,3,5,6])

map()的功能是将函数对象依次作用于表的每一个元素,每次作用的结果储存于返回的表re中。
map通过读入的函数(这里是lambda函数)来操作数据(这里“数据”是表中的每一个元素,“操作”是对每个数据加3)。

如果作为参数的函数对象有多个参数,可使用下面的方式,向map()传递函数参数的多个参数:

1
2
re = map((lambda x,y: x+y),[1,2,3],[6,7,9])
#map()将每次从两个表中分别取出一个元素,带入lambda所定义的函数。

4、filter()函数

它也是将作为参数的函数对象作用于多个元素。如果函数对象返回的是True,则该次的元素被储存于返回的表中。 filter通过读入的函数来筛选数据。

1
2
3
4
5
6
7
def func(a):
if a > 100:
return True
else:
return False
print filter(func,[10,56,101,500])

5、reduce()函数

reduce函数的第一个参数也是函数,但有一个要求,就是这个函数自身能接收两个参数。reduce可以累进地将函数作用于各个参数:

1
2
print reduce((lambda x,y: x+y),[1,2,5,7,9])
#相当于(((1+2)+5)+7)+9

reduce将表中的前两个元素(1和2)传递给lambda函数,得到3。该返回值(3)将作为lambda函数的第一个参数,而表中的下一个元素(5)作为lambda函数的第二个参数,进行下一次的对lambda函数的调用,得到8。依次调用lambda函数,每次lambda函数的第一个参数是上一次运算结果,而第二个参数为表中的下一个元素,直到表中没有剩余元素。

错误处理

1、异常处理

eg:

1
2
3
4
5
6
re = iter(range(5))
for i in range(100):
print re.next()
print 'HaHa'

异常处理:

1
2
3
4
5
6
7
8
9
re = iter(range(5))
try:
for i in range(100):
print re.next()
except StopIteration:
print 'Here is the end', i
print 'HaHa'

语法结构如下:

1
2
3
4
5
6
7
8
9
10
11
12
try:
...
except exception1:
...
except exception2:
...
except:
...
else:
...
finally:
...

流程如下:

  • try->异常->except->finally

  • try->无异常->else->finally

2、抛出异常

动态类型

1、动态类型

2、从动态类型看函数的参数传递