循环可以有一个 else 子句;它在循环迭代完整个列表(对于 for )或执行条件 为 false (对于 while )时执行,但循环被 break 中止的情况下不会执行。
以下搜索素数的示例程序演示了这个子句
for n in range(2, 10):
for x in range(2, n):
if n % x == 0:
print n, 'equals', x, '*', n/x
break
else:
# loop fell through without finding a factor
print n, 'is a prime number'
默认值在函数 定义 作用域被解析,如下所示
i = 5
def f(arg=i):
print arg
i = 6
f()
will print 5.
引入一个形如 **name 的参数时,它接收一个字典(参见 typesmapping ) ,该字典包含了所有未出现 在形式参数列表中的关键字参数。
这里可能还会组合使用一个形如 *name (下一小节詳細介绍) 的形 式 参数,它接收一个元组(下一节中会详细介绍),包含了所有没有出现在形式 参数列表中的参数值。
( *name 必须在 **name 之前出现) 例如,我们这样定 义一个函数
def cheeseshop(kind, *arguments, **keywords):
print "-- Do you have any", kind, "?"
print "-- I'm sorry, we're all out of", kind
for arg in arguments: print arg
print "-" * 40
keys = keywords.keys()
keys.sort()
for kw in keys: print kw, ":", keywords[kw]
It could be called like this:
它可以像这样调用
cheeseshop("Limburger", "It's very runny, sir.",
"It's really very, VERY runny, sir.",
shopkeeper='Michael Palin',
client="John Cleese",
sketch="Cheese Shop Sketch")
and of course it would print:
当然它会按如下内容打印
-- Do you have any Limburger ?
-- I'm sorry, we're all out of Limburger
It's very runny, sir.
It's really very, VERY runny, sir.
----------------------------------------
client : John Cleese
shopkeeper : Michael Palin
sketch : Cheese Shop Sketch
出于实际需要,有几种通常在函数式编程语言例如 Lisp 中出现的功能加入到了 Python 。
通过 lambda 关键字,可以创建短小的匿名函数。这里有一个函数返 回它的两个参数的和: lambda a, b: a+b 。
Lambda 形式可以用于任何需要的 函数对象。出于语法限制,它们只能有一个单独的表达式。
语义上讲,它 们只是 普通函数定义中的一个语法技巧。类似于嵌套函数定义,lambda 形式可以从外部作用域引用变量。
>>> def make_incrementor(n):
... return lambda x: x + n
...
>>> f = make_incrementor(42)
>>> f(0)
42
>>> f(1)
43
你也可以把链表当做队列使用,队列作为特定的数据结构,最先进入的元素最先 释放(先进先出)。不 过,列表这样用效率不高。
相对来说从列表末尾添加和弹 出很快;在头部插入和弹出很慢(因为,为了一 个元素,要移动整个列表中的所 有元素)。
要实现队列,使用 collections.deque ,它为在首尾两端快速插入和 删除而设计。例如
>>> from collections import deque
>>> queue = deque(["Eric", "John", "Michael"])
>>> queue.append("Terry") # Terry arrives
>>> queue.append("Graham") # Graham arrives
>>> queue.popleft() # The first to arrive now leaves
'Eric'
>>> queue.popleft() # The second to arrive now leaves
'John'
>>> queue # Remaining queue in order of arrival
deque(['Michael', 'Terry', 'Graham'])
filter(function, sequence) 返回一个sequence(序列),包括了给定序列中所有调用 function(item) 后返回值为true的元素。(如果可能的话, 会返回相同的类型)。
如果该序列(sequence) 是一个 string (字符串)或者 tuple (元组),返回值必定是同一类型,否则,它 总是 list 。
>>> def f(x): return x % 2 != 0 and x % 3 != 0
...
>>> filter(f, range(2, 25))
[5, 7, 11, 13, 17, 19, 23]
map(function, sequence) 为每一个元素依次调用 function(item) 并将返回值 组成一个链表返回。例 如,以下程序计算立方
>>> def cube(x): return x*x*x
...
>>> map(cube, range(1, 11))
[1, 8, 27, 64, 125, 216, 343, 512, 729, 1000]
可以传入多个序列,函数也必须要有对应数量的参数,执行时会依次用各序列上 对应的元素来调用函数 (如果某些序列比其它的短,就用 None 来代替)。
如果把 None做为一个函数传入,则直接返回参数做为替代。例如
>>> seq = range(8)
>>> def add(x, y): return x+y
...
>>> map(add, seq, seq)
[0, 2, 4, 6, 8, 10, 12, 14]
reduce(func, sequence) 返回一个单值,它是这样构造的:首先以序列的 前两个元素调用函数 function ,再以返回值和第三个参数调用,依次执行下去。
例如,以 下程序计算 1 到 10 的整数之和
>>> def add(x,y): return x+y
...
>>> reduce(add, range(1, 11))
55
acquire参数为false不阻塞:
List Comprehensions 列表推导式
列表推导式比 map() 更复杂,可使用复杂的表达式和嵌套函数
>>> freshfruit = [' banana', ' loganberry ', 'passion fruit ']
>>> [weapon.strip() for weapon in freshfruit]
['banana', 'loganberry', 'passion fruit']
>>> vec = [2, 4, 6]
>>> [3*x for x in vec]
[6, 12, 18]
>>> [3*x for x in vec if x > 3]
[12, 18]
>>> [3*x for x in vec if x < 2]
[]
>>> [[x,x**2] for x in vec]
[[2, 4], [4, 16], [6, 36]]
>>> [x, x**2 for x in vec] # error - parens required for tuples
File "<stdin>", line 1, in ?
[x, x**2 for x in vec]
^
SyntaxError: invalid syntax
>>> [(x, x**2) for x in vec]
[(2, 4), (4, 16), (6, 36)]
>>> vec1 = [2, 4, 6]
>>> vec2 = [4, 3, -9]
>>> [x*y for x in vec1 for y in vec2]
[8, 6, -18, 16, 12, -36, 24, 18, -54]
>>> [x+y for x in vec1 for y in vec2]
[6, 5, -7, 8, 7, -5, 10, 9, -3]
>>> [vec1[i]*vec2[i] for i in range(len(vec1))]
[8, 12, -54]
Looping Techniques 循环技巧
在字典中循环时,关键字和对应的值可以使用 iteritems() 方法同时解读出来
>>> knights = {'gallahad': 'the pure', 'robin': 'the brave'}
>>> for k, v in knights.iteritems():
... print k, v
...
gallahad the pure
robin the brave
When looping through a sequence, the position index and corresponding value can be retrieved at
the same time using the enumerate() function. :
在序列中循环时,索引位置和对应值可以使用 enumerate() 函数同时得 到。
>>> for i, v in enumerate(['tic', 'tac', 'toe']):
... print i, v
...
0 tic
1 tac
2 toe
To loop over two or more sequences at the same time, the entries can be paired with the zip()
function. :
同时循环两个或更多的序列,可以使用 zip() 整体打包。
>>> questions = ['name', 'quest', 'favorite color']
>>> answers = ['lancelot', 'the holy grail', 'blue']
>>> for q, a in zip(questions, answers):
... print 'What is your {0}? It is {1}.'.format(q, a)
...
What is your name? It is lancelot.
What is your quest? It is the holy grail.
What is your favorite color? It is blue.
To loop over a sequence in reverse, first specify the sequence in a forward direction and then
call the reversed() function. :
需要逆向循环序列的话,先正向定位序列,然后调用 reversed() 函数
>>> for i in reversed(xrange(1,10,2)):
... print i
...
9
7
5
3
1
To loop over a sequence in sorted order, use the sorted() function which returns a new sorted
list while leaving the source unaltered.
要按排序后的顺序循环序列的话,使用 sorted() 函数,它不改动原序列,而是 生成一个新的已排序的序
列。
``Compiled'' Python files “编译的” Python 文件
对于引用了大量标准模块的短程序,有一个提高启动速度的重要方法,如果在 spam.py 所在的目录下存 在一个名为 spam.pyc 的文件,它会 被视为 spam 模块的预“编译”(``byte-compiled'' ,二进制编 译) 版本。
用于创建 spam.pyc 的这一版 spam.py 的修改时间记 录在 spam.pyc 文件中,如果两者不匹 配,.pyc 文件就被忽略。
通常你不需要为创建 spam.pyc 文件做任何工作。一旦 spam.py 成功编译,就 会尝试生成对应版本的 spam.pyc 。
以 -O 参数调用Python解释器时,会生成优化代码并保存在 .pyo 文件中。现 在的优化器没有太多 帮助;它只是删除了断言( assert )语句。
使用 -O 参 参数, 所有 的字节码( bytecode )都 会被优化; .pyc 文 件被忽略, .py 文件被编译为优化代码。
来自 .pyc 文件或 .pyo 文件中的程序不会比来自 .py 文件的运行更快; .pyc 或 .pyo 文件只是在它们加载的时候更快一些。
dir()函数 列出了所有类型的名称:变量,模块,函数,等等。
dir() 不会列出内置函数和变量名。如果你想列出这些内容,它们在标准模块 builtin 中定义
Packages 包
对于包的作者来说唯一的解决方案就是给提供一个明确的包索引。 import 语句按如下条件进行转换: 执行 from package import * 时,如果包中的 __init__ .py 代码定义了一个名为__all__的列表,就 会按照列表中给出的模块名进行导入。
新版本的包发布时作者可以任 意更新这个列表。如果包作者不想 import * 的时候导入他们的包中所有模块, 那么也可能会决定不支持它(import *)。例如, Sounds/ Effects/ init .py 这个文件可能包括如下代码
__all__ = ["echo", "surround", "reverse"]
这意味着 from Sound.Effects import * 语句会从 sound 包中导入以上三个已命名的子模块。
有两种方式可以写平方和立方表
>>> for x in range(1, 11):
... print repr(x).rjust(2), repr(x*x).rjust(3),
... # Note trailing comma on previous line
... print repr(x*x*x).rjust(4)
...
1 1 1
2 4 8
3 9 27
4 16 64
5 25 125
6 36 216
7 49 343
8 64 512
9 81 729
10 100 1000
>>> for x in range(1,11):
... print '{0:2d} {1:3d} {2:4d}'.format(x, x*x, x*x*x)
...
1 1 1
2 4 8
3 9 27
4 16 64
5 25 125
6 36 216
7 49 343
还有另一个方法, zfill() 它用于向数值的字符串表达左侧填充 0。该 函数可以正确理解正负号
>>> '12'.zfill(5)
'00012'
>>> '-3.14'.zfill(7)
'-003.14'
>>> '3.14159265359'.zfill(5)
'3.14159265359'
类
__doc__ 也是一个有效的属性,返回类的文档字符串。
客户应该小心使用数据属性--客户可能会因为随意修改数据属性而破坏了本来由方法维护的数据一致性。需要注意的是,客户只要注意避免命名冲突,就可以 随意向实例中添加数据属性而不会影响方法的有效性 .
Python 有两个用于继承的函数:
函数 isinstance() 用于检查实例类型: isinstance(obj, int) 只有在 obj.__class__ 是 int 或其它从 int 继承 的类型.
函数 issubclass() 用于检查类继承: issubclass(bool, int) 为 True ,因为 bool 是 int 的子类。但是, issubclass(unicode, str) 是 False ,因为 unicode 不 是 str 的子类(它们只是共享一个通用祖先类 basestring )。
super用来执行父类中的函数:
class Foo(object):
def hi(self):
print 'hi,Foo'
class Foo2(Foo):
def hi(self):
super(Foo2, self).hi()
if __name__ == '__main__':
foo2 = Foo2()
foo2.hi()
运行结果:
hi,Foo
注意,Foo类必须继承某个类(并且这个继承链开始于object类),否则会报错。
只能从对像内部访问的“私有”实例变量,在 Python 中不存在。然而,也有 一个变通的访问用于大多数 Python 代码:以一个下划线开头的命名(例如_spam )会被处理为 API 的非公开部分(无论它是一个函数、方法或数据 成员)。它会被视为一个实现细节,无需公开。
有时类似于Pascal中“记录(record)”或C中“结构(struct)”的数据类型 很有用,它将一组已命名的 数据项绑定在一起。一个空的类定义可以很好的实现:
class Employee:
pass
john = Employee() # Create an empty employee record
# Fill the fields of the record
john.name = 'John Doe'
john.dept = 'computer lab'
john.salary = 1000
for 遍历:
for element in [1, 2, 3]:
print element
for element in (1, 2, 3):
print element
for key in {'one':1, 'two':2}:
print key
for char in "123":
print char
for line in open("myfile.txt"):
print line
在后台, for 语句在容器 对象中调用 iter() 。 该函数返回一个定义了 next() 方法的迭代器对象,它在容器中逐一访问元素。 没 有后续的元素时, next() 抛出一个 StopIteration 异常通知 for 语句循环结束。
>>> s = 'abc' >>> it = iter(s) >>> it <iterator object at 0x00A1DB50> >>> it.next() 'a' >>> it.next() 'b' >>> it.next() 'c' >>> it.next()
Traceback (most recent call last): File "", line 1, in ? it.next() StopIteration
了解了迭代器协议的后台机制,就可以很容易的给自己的类添加迭代器行为。定 义一个 iter () 方法, 使其返回一个带有 next() 方法的对象。如果这个类 已经定义了 next() ,那么 iter () 只需要返回 self
class Reverse:
"Iterator for looping over a sequence backwards"
def init (self, data):
self.data = data
self.index = len(data)
def iter (self):
return self
def next(self):
if self.index == 0:
raise StopIteration
self.index = self.index - 1
return self.data[self.index]
>>> for char in Reverse('spam'):
... print char
...
m
a
p
s
Generators 生成器:
def reverse(data):
for index in range(len(data)-1, -1, -1):
yield data[index]
>>> for char in reverse('golf'):
... print char
...
f
l
o
g