命令行
命令行可以运行Python程序。通过使用:python xxx.py
如果想要加上一些参数:参考链接
在Python命令行中下划线有特殊的作用,代表前一个计算出的结果。
声明文件编码:
# coding=utf-8
计算器
关于隐式类型转换需要注意。
计算符号需要注意,不会可参考下面的代码:
17 / 3.0 # int / float -> float
17 // 3.0 # explicit floor division discards the fractional part
5.0
17 % 3 # the % operator returns the remainder of the division
2
5 ** 2 # 5 squared
25
2 ** 7 # 2 to the power of 7
128
变量必须在声明时赋值,与此同时会确定类型。
字符串
单引号和双引号都能表示字符串。区别在于转义的时候。
如果懒得加转义字符,可以通过在字符串前面加上r。例如:
print r'C:\some\name'
通过在字符串里面添加反斜杠来不换行。
print """\
Usage: thingy [OPTIONS]
-h Display this usage message
-H hostname Hostname to connect to
"""
字符串通过加号来连接,并可以通过乘号来翻倍。
字符串也可以通过写在一起来连接,但是不能用在变量上面:
'Py' 'thon'
字符串可以像数组一样访问,0代表开始字符。特别的是,-1代表最后一个字符,-2表示倒数第2个字符,依次得到结果。
字符串可以切片访问。比较特别的是使用负数来切片。
s="abcde"
s[0]
s[-1]
s[-5]
s[:-1] #去掉最后一个字符,比如换行符
+---+---+---+---+---+---+
| P | y | t | h | o | n |
+---+---+---+---+---+---+
0 1 2 3 4 5 6
-6 -5 -4 -3 -2 -1
切片访问越界会得到一个空集。无需做访问控制。
对于单个字符时无法赋值的,因为字符串是不可变的。如果需要一个不同的字符串,那就creat一个新的字符串吧,使用切片能够很容易达到这点。
内置函数len返回字符串的长度。
用encode和decode来问字符串编码解码。(关于编码类型的问题,需要专门开一个文件来讨论)
list列表
list与string差不多,两者区别在于,list可以修改,string不可以。
list可以嵌套,并且可以通过二维引用去取值,不要忘记这个特性。
编程特性
看下面的例子:
a, b = 0, 1
while b < 10:
print b
a, b = b, a+b
Python支持多重赋值,很有意思的一点。
while语句的条件无需括号,简化了。条件符号包含:> < == <= >=
循环控制工具
除了wihle还有一些循环和控制语句。
比如说if语句:
if x < 0:
x = 0
print 'Negative changed to zero'
elif x == 0:
print 'Zero'
elif x == 1:
print 'Single'
else:
print 'More'
for循环与while循环是不同的,更多用于遍历:
words = ['cat', 'window', 'defenestrate']
for w in words:
print w, len(w)
注意:在遍历的时候同时修改待遍历的list是危险的(考虑不断在list后面加的情况)。
因此需要遍历的时候,使用切片返回一个list副本将会是一个安全的作法。
for w in words[:]:
if len(w) > 6:
words.insert(0, w)
如果需要返回一串顺序的数字list,可以用range:
range(10)
range(5, 10)
range(0, 10, 3)=[0, 3, 6, 9]
range(-10, -100, -30)=[-10, -40, -70]
由于range的存在,可以使用下面这种方法遍历list:
a = ['Mary', 'had', 'a', 'little', 'lamb']
for i in range(len(a)):
print i, a[i]
break和continue不用多说,但是循环加上else还是挺有意思的。
for n in range(2, 10):
for x in range(2, n):
if n % x == 0:
print n, 'equals', x, '*', n/x
else:
print n, 'is a prime number'
是的,没有看错,else是给for用的。
表达的意思是指,如果for不是break退出的,则运行else。
pass语句代表空语句,用来占位用的。
定义函数
Python的函数不需要返回值类型。
函数定义之后可以作为变量赋值。
如果一个函数没有返回值,那么会返回一个None。如果需要返回值,显示的return。
一个典型的python是想下面这样的:
def fib2(n):
result = []
a, b = 0, 1
while a < n:
result.append(a) # see below
a,b=b,a+b
return result
更多有关函数定义
Python的函数参数可以设置默认值,形如:
def ask_ok(prompt, retries=4, complaint='Yes or no, please!')
有关默认值,需要注意的是,如果给可变数据的类型如list设置默认值为空,那么再次调用此函数会使用之前的那个list而不是空。比如:
def f(a, L=[]):
L.append(a)
return L
print f(1)
print f(2)
print f(3)
[1]
[1, 2]
[1, 2, 3]
这当然不是我们想要的结果。所以正确的作法是应该写成None:
def f(a, L=None):
if L is None:
L = []
L.append(a)
return L
当然,Python很灵活,提供你在调用函数的时候使用关键词来给出参数:
parrot(voltage=1000)
但是灵活不代表没有规则,关于参数,需要严格按照函数的需要来给出。没有默认值的要给出参数值,如果不指明关键词,那么将会按照顺序读取你的参数。
对于较为复杂的函数参数,建议还是输入关键词为好。避免出现不必要的错误。
来看一个比较复杂的函数参数例子:
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 = sorted(keywords.keys())
for kw in keys:
print kw, ":", keywords[kw]
cheeseshop("Limburger", "It's very runny, sir.",
"It's really very, VERY runny, sir.",
shopkeeper='Michael Palin',
client="John Cleese",
sketch="Cheese Shop Sketch")
-- 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
星号name 必须在 double星号name 之前。
星号name接受多个无关键词的参数。
double接受有关键词的参数。
double星号name 其实就是一个元组。传递时使用double星号
lambda表达式
也就是一个函数,运行时才确定函数执行的属性和方法。形如:
def make_incrementor(n):
return lambda x: x + n
f = make_incrementor(42)
f(0)=42
f(1)=43
pairs = [(1, 'one'), (2, 'two'), (3, 'three'), (4, 'four')]
pairs.sort(key=lambda pair: pair[1])
pairs=[(4, 'four'), (1, 'one'), (3, 'three'), (2, 'two')]
注释
单行注释是#
多行注释为三个双引号nothing三个双引号,关于多行注释,注意形如:
def my_function():
"""Do noting
no real do nothing
"""
pass
print my_function.__doc__
Do nothing, but document it.
No, really, it doesn't do anything.
编程风格
写的多自然就懂了
数据存储细节
more on lists
list对象提供了很多方法可以使用,比如说下面这些:
list.append(x)
Add an item to the end of the list; equivalent to a[len(a):] = [x].list.extend(L)
Extend the list by appending all the items in the given list; equivalent to a[len(a):] = L.list.insert(i, x)
Insert an item at a given position. The first argument is the index of the element before which to insert, so a.insert(0, x) inserts at the front of the list, and a.insert(len(a), x) is equivalent to a.append(x).list.remove(x)
Remove the first item from the list whose value is x. It is an error if there is no such item.list.pop([i])
Remove the item at the given position in the list, and return it. If no index is specified, a.pop() removes and returns the last item in the list. (The square brackets around the i in the method signature denote that the parameter is optional, not that you should type square brackets at that position. You will see this notation frequently in the Python Library Reference.)list.index(x)
Return the index in the list of the first item whose value is x. It is an error if there is no such item.list.count(x)
Return the number of times x appears in the list.list.sort(cmp=None, key=None, reverse=False)
Sort the items of the list in place (the arguments can be used for sort customization, see sorted() for their explanation).list.reverse()
Reverse the elements of the list, in place.
例子如下所示:
>>> a = [66.25, 333, 333, 1, 1234.5]
>>> print a.count(333), a.count(66.25), a.count('x')
2 1 0
>>> a.insert(2, -1)
>>> a.append(333)
>>> a
[66.25, 333, -1, 333, 1, 1234.5, 333]
>>> a.index(333)
1
>>> a.remove(333)
>>> a
[66.25, -1, 333, 1, 1234.5, 333]
>>> a.reverse()
>>> a
[333, 1234.5, 1, 333, -1, 66.25]
>>> a.sort()
>>> a
[-1, 1, 66.25, 333, 333, 1234.5]
>>> a.pop()
1234.5
>>> a
[-1, 1, 66.25, 333, 333]
把list当做stack来用
比如下面:
>>> stack = [3, 4, 5]
>>> stack.append(6)
>>> stack.append(7)
>>> stack
[3, 4, 5, 6, 7]
>>> stack.pop()
7
>>> stack
[3, 4, 5, 6]
>>> stack.pop()
6
>>> stack.pop()
5
>>> stack
[3, 4]
把list当做队列来用
比如下面:
>>> 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()、map()、reduce()
filter(function, sequence)返回一个筛选过后的列表。
>>> def f(x): return x % 3 == 0 or x % 5 == 0
...
>>> filter(f, range(2, 25))
[3, 5, 6, 9, 10, 12, 15, 18, 20, 21, 24]
map(function, sequence)对于每一个在sequence内的元素,调用function。
>>> def cube(x): return x*x*x
...
>>> map(cube, range(1, 11))
[1, 8, 27, 64, 125, 216, 343, 512, 729, 1000]
reduce(function, sequence)返回一个单一的值。与map不同,map返回的是一个list列表。
reduce其实就是把前一轮计算的值作为参数,继续进行下一轮的计算。
>>> def add(x,y): return x+y
...
>>> reduce(add, range(1, 11))
55
reduce还有第三个参数,用来设置轮回的初始值:
>>> def sum(seq):
... def add(x,y): return x+y
... return reduce(add, seq, 0)
...
>>> sum(range(1, 11))
55
>>> sum([])
0
列表推导
比如说,我们想要创建一个数据平方的列表:
>>> squares = []
>>> for x in range(10):
... squares.append(x**2)
...
>>> squares
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
更简便直接的创建方法其实是:
squares = [x**2 for x in range(10)]
#当然用下面的lamda表达式也行
squares = map(lambda x: x**2, range(10))
列表表示完全可以写的更加复杂,比如说:
>>> [(x, y) for x in [1,2,3] for y in [3,1,4] if x != y]
[(1, 3), (1, 4), (2, 3), (2, 1), (2, 4), (3, 1), (3, 4)]
#这等于:
>>> combs = []
>>> for x in [1,2,3]:
... for y in [3,1,4]:
... if x != y:
... combs.append((x, y))
...
>>> combs
[(1, 3), (1, 4), (2, 3), (2, 1), (2, 4), (3, 1), (3, 4)]
如果表达式里面有括弧,那么就肯定是一个元组啦:
>>> vec = [-4, -2, 0, 2, 4]
>>> # create a new list with the values doubled
>>> [x*2 for x in vec]
[-8, -4, 0, 4, 8]
>>> # filter the list to exclude negative numbers
>>> [x for x in vec if x >= 0]
[0, 2, 4]
>>> # apply a function to all the elements
>>> [abs(x) for x in vec]
[4, 2, 0, 2, 4]
>>> # call a method on each element
>>> freshfruit = [' banana', ' loganberry ', 'passion fruit ']
>>> [weapon.strip() for weapon in freshfruit]
['banana', 'loganberry', 'passion fruit']
>>> # create a list of 2-tuples like (number, square)
>>> [(x, x**2) for x in range(6)]
[(0, 0), (1, 1), (2, 4), (3, 9), (4, 16), (5, 25)]
>>> # the tuple must be parenthesized, otherwise an error is raised
>>> [x, x**2 for x in range(6)]
File "<stdin>", line 1
[x, x**2 for x in range(6)]
^
SyntaxError: invalid syntax
>>> # flatten a list using a listcomp with two 'for'
>>> vec = [[1,2,3], [4,5,6], [7,8,9]]
>>> [num for elem in vec for num in elem]
[1, 2, 3, 4, 5, 6, 7, 8, 9]
list表达式能够使用复杂的表达式,并且能够嵌套函数:
>>> from math import pi
>>> [str(round(pi, i)) for i in range(1, 6)]
['3.1', '3.14', '3.142', '3.1416', '3.14159']
列表推导嵌套
列表推导是能够嵌套着来的,比如说:
>>> matrix = [
... [1, 2, 3, 4],
... [5, 6, 7, 8],
... [9, 10, 11, 12],
... ]
>>> [[row[i] for row in matrix] for i in range(4)]
[[1, 5, 9], [2, 6, 10], [3, 7, 11], [4, 8, 12]]
#上面这个程序能够把行列表转为列列表
上面的程序等同于下面:
>>> transposed = []
>>> for i in range(4):
... transposed.append([row[i] for row in matrix])
...
>>> transposed
[[1, 5, 9], [2, 6, 10], [3, 7, 11], [4, 8, 12]]
也等于下面:
>>> transposed = []
>>> for i in range(4):
... # the following 3 lines implement the nested listcomp
... transposed_row = []
... for row in matrix:
... transposed_row.append(row[i])
... transposed.append(transposed_row)
...
>>> transposed
[[1, 5, 9], [2, 6, 10], [3, 7, 11], [4, 8, 12]]
用哪个呢?肯定是列表嵌套简单明了啦,哈哈。
有没有更好的方法呢?当然就是内建函数啦,这种函数都经过优化,效率什么的都是杠杠的。
>>> zip(*matrix)
[(1, 5, 9), (2, 6, 10), (3, 7, 11), (4, 8, 12)]
del语句
除了list的remove之外,还有一种方法:del 能够删除list的元素。del的强大之处,在于支持切片删除哦。
>>> a = [-1, 1, 66.25, 333, 333, 1234.5]
>>> del a[0]
>>> a
[1, 66.25, 333, 333, 1234.5]
>>> del a[2:4]
>>> a
[1, 66.25, 1234.5]
>>> del a[:]
>>> a
[]
del也能够用来删除整个变量:
del a
元组和序列
talk is cheap,关于元组,看下面的例子:
>>> t = 12345, 54321, 'hello!'
>>> t[0]
12345
>>> t
(12345, 54321, 'hello!')
>>> # Tuples may be nested:
... u = t, (1, 2, 3, 4, 5)
>>> u
((12345, 54321, 'hello!'), (1, 2, 3, 4, 5))
>>> # Tuples are immutable:
... t[0] = 88888
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'tuple' object does not support item assignment
>>> # but they can contain mutable objects:
... v = ([1, 2, 3], [3, 2, 1])
>>> v
([1, 2, 3], [3, 2, 1])
元组的普通元素是不能修改的。但是元组内的list可以修改。
关于元组的一些特性,可以看下面:
>>> empty = ()
>>> singleton = 'hello', # <-- note trailing comma
>>> len(empty)
0
>>> len(singleton)
1
>>> singleton
('hello',)
如果想要初始化一个元组,且是只有一个元素,为了单个元组赋值做区分,后面加个逗号。
元组的还支持拆分,比如说:
t=12345, 54321, 'hello!'
x, y, z = t
集合
集合一个容器,里面没有重复的数据。典型的用途是消除重复数据。当然也能用来测试是否存在重复数据。
看code:
>>> basket = ['apple', 'orange', 'apple', 'pear', 'orange', 'banana']
>>> fruit = set(basket) # create a set without duplicates
>>> fruit
set(['orange', 'pear', 'apple', 'banana'])
>>> 'orange' in fruit # fast membership testing
True
>>> 'crabgrass' in fruit
False
>>> # Demonstrate set operations on unique letters from two words
...
>>> a = set('abracadabra')
>>> b = set('alacazam')
>>> a # unique letters in a
set(['a', 'r', 'b', 'c', 'd'])
>>> a - b # letters in a but not in b
set(['r', 'd', 'b'])
>>> a | b # letters in either a or b
set(['a', 'c', 'r', 'd', 'b', 'm', 'z', 'l'])
>>> a & b # letters in both a and b
set(['a', 'c'])
>>> a ^ b # letters in a or b but not both
set(['r', 'd', 'b', 'm', 'z', 'l'])
集合能做一些加减交并的操作。
类似列表推导,集合也支持:
>>> a = {x for x in 'abracadabra' if x not in 'abc'}
>>> a
set(['r', 'd'])
集合推导用{}包住。不过我在command里面运行出错,不知道什么原因。
字典
字典就是就是键值对类型的数据集合。大概是下面这样的:
>>> tel = {'jack': 4098, 'sape': 4139}
>>> tel['guido'] = 4127
>>> tel
{'sape': 4139, 'guido': 4127, 'jack': 4098}
>>> tel['jack']
4098
>>> del tel['sape']
>>> tel['irv'] = 4127
>>> tel
{'guido': 4127, 'irv': 4127, 'jack': 4098}
>>> tel.keys()
['guido', 'irv', 'jack']
>>> 'guido' in tel
True
dic函数通过一个列表构建出一个序列:
>>> dict([('sape', 4139), ('guido', 4127), ('jack', 4098)])
{'sape': 4139, 'jack': 4098, 'guido': 4127}
当然啦,字典可以通过表达式来生成:
>>> {x: x**2 for x in (2, 4, 6)}
{2: 4, 4: 16, 6: 36}
如果key是简单字符串的话,更加容易访问:
>>> dict(sape=4139, guido=4127, jack=4098)
{'sape': 4139, 'jack': 4098, 'guido': 4127}
循环技术
当要对一个序列做遍历的时候哦,大概是这样的:
>>> for i, v in enumerate(['tic', 'tac', 'toe']):
... print i, v
...
0 tic
1 tac
2 toe
如果想要循环的同时搞好几个序列的话,用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.
如果想要逆序,这样子来:
>>> for i in reversed(xrange(1,10,2)):
... print i
...
9
7
5
3
1
想要遍历排序之后的话:
>>> basket = ['apple', 'orange', 'apple', 'pear', 'orange', 'banana']
>>> for f in sorted(set(basket)):
... print f
...
apple
banana
orange
pear
如果想要遍历一个字典,一般都要同时拿到key和value,可以这么做:
>>> knights = {'gallahad': 'the pure', 'robin': 'the brave'}
>>> for k, v in knights.iteritems():
... print k, v
...
gallahad the pure
robin the brave
还是那个要注意的地方,如果需要遍历的时候修改,使用一个copy。
>>> words = ['cat', 'window', 'defenestrate']
>>> for w in words[:]: # Loop over a slice copy of the entire list.
... if len(w) > 6:
... words.insert(0, w)
...
>>> words
['defenestrate', 'cat', 'window', 'defenestrate']
条件表达式
有哪些条件表达式呢?
简单的符号自然不用讲了:
in 和 not in:代表检查元素是否在序列中
is 和 is not:检查是否是同一个东西
and 和 or:代表与和或的逻辑
不用去记忆优先级,用括号吧,而且方便阅读。
举个例子:
>>> string1, string2, string3 = '', 'Trondheim', 'Hammer Dance'
>>> non_null = string1 or string2 or string3
>>> non_null
'Trondheim'
序列之间的比较是逐个进行的:
(1, 2, 3) < (1, 2, 4)
[1, 2, 3] < [1, 2, 4]
'ABC' < 'C' < 'Pascal' < 'Python'
(1, 2, 3, 4) < (1, 2, 4)
(1, 2) < (1, 2, -1)
(1, 2, 3) == (1.0, 2.0, 3.0)
(1, 2, ('aa', 'ab')) < (1, 2, ('abc', 'a'), 4)
模块
Python里面一个模块就是一个文件。
比如说下面这个模块:
# Fibonacci numbers module
def fib(n): # write Fibonacci series up to n
a, b = 0, 1
while b < n:
print b,
a, b = b, a+b
def fib2(n): # return Fibonacci series up to n
result = []
a, b = 0, 1
while b < n:
result.append(b)
a, b = b, a+b
return result
使用的时候得这样:
>>> import fibo
>>> fibo.fib(1000)
1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987
>>> fibo.fib2(100)
[1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]
>>> fibo.__name__
'fibo'
通过调用name可以得到模块名称。
如果你经常使用某个函数,完全可以这样子:
>>> fib = fibo.fib
>>> fib(500)
1 1 2 3 5 8 13 21 34 55 89 144 233 377
更多的模块
一般来说,使用模块推荐的方式是导入固定的函数,如下所示:
>>> from fibo import fib, fib2
>>> fib(500)
1 1 2 3 5 8 13 21 34 55 89 144 233 377
或者:
>>> from fibo import *
>>> fib(500)
1 1 2 3 5 8 13 21 34 55 89 144 233 377
使得模块像脚本一样运行
像下面这样:
python fibo.py <arguments>
if __name__ == "__main__":
import sys
fib(int(sys.argv[1]))
$ python fibo.py 50
1 1 2 3 5 8 13 21 34
模块的搜索路径
大致过程是:
- 搜索内建模块
- 搜索sys.path,sys.path来自于:
运行脚本所在的当前目录
PYTHONPATH环境变量
默认的安装依赖
编译
这个暂时先不搞,等以后有需要开专题。
标准模块
可以通过下面的命令去扩展模块搜索:
>>> import sys
>>> sys.path.append('/ufs/guido/lib/python')
dir函数
这个函数可以得到模块提供的函数。
如果么有参数,会得到已经定义的名字。
>>> import fibo, sys
>>> dir(fibo)
['__name__', 'fib', 'fib2']
>>> a = [1, 2, 3, 4, 5]
>>> import fibo
>>> fib = fibo.fib
>>> dir()
['__builtins__', '__name__', '__package__', 'a', 'fib', 'fibo', 'sys']
注意,列出来的东西包括所有名称:变量、模块、函数等等。
导入和包
两种导入方式:
import sound.effects.echo
import sound.effects.surround
from sound.effects import *
如何从一个包中导入所有模块呢??
可以在包下面新建一个文件:init.py:
all__ = ["echo", "surround", "reverse"]
然后:from package import 星号
输入输出
str和repr都能用来转化数据位字符串。
repr面向解释器,str面向人类可读。
>>> s = 'Hello, world.'
>>> str(s)
'Hello, world.'
>>> repr(s)
"'Hello, world.'"
>>> str(1.0/7.0)
'0.142857142857'
>>> repr(1.0/7.0)
'0.14285714285714285'
>>> x = 10 * 3.25
>>> y = 200 * 200
>>> s = 'The value of x is ' + repr(x) + ', and y is ' + repr(y) + '...'
>>> print s
The value of x is 32.5, and y is 40000...
>>> # The repr() of a string adds string quotes and backslashes:
... hello = 'hello, world\n'
>>> hellos = repr(hello)
>>> print hellos
'hello, world\n'
>>> # The argument to repr() may be any Python object:
... repr((x, y, ('spam', 'eggs')))
"(32.5, 40000, ('spam', 'eggs'))"
下面有两种方式格式化输出:
>>> 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
8 64 512
9 81 729
10 100 1000
str.format方法很好用,比如说:
>>> print 'We are the {} who say "{}!"'.format('knights', 'Ni')
We are the knights who say "Ni!"
>>> print '{0} and {1}'.format('spam', 'eggs')
spam and eggs
>>> print '{1} and {0}'.format('spam', 'eggs')
eggs and spam
>>> print 'This {food} is {adjective}.'.format(
... food='spam', adjective='absolutely horrible')
This spam is absolutely horrible.
>>> print 'The story of {0}, {1}, and {other}.'.format('Bill', 'Manfred',
... other='Georg')
The story of Bill, Manfred, and Georg.
#'!s' (apply str()) and '!r' (apply repr())
>>> import math
>>> print 'The value of PI is approximately {}.'.format(math.pi)
The value of PI is approximately 3.14159265359.
>>> print 'The value of PI is approximately {!r}.'.format(math.pi)
The value of PI is approximately 3.141592653589793.
>>> import math
>>> print 'The value of PI is approximately {0:.3f}.'.format(math.pi)
The value of PI is approximately 3.142.
>>> table = {'Sjoerd': 4127, 'Jack': 4098, 'Dcab': 7678}
>>> for name, phone in table.items():
... print '{0:10} ==> {1:10d}'.format(name, phone)
...
Jack ==> 4098
Dcab ==> 7678
Sjoerd ==> 4127
>>> table = {'Sjoerd': 4127, 'Jack': 4098, 'Dcab': 8637678}
>>> print ('Jack: {0[Jack]:d}; Sjoerd: {0[Sjoerd]:d}; '
... 'Dcab: {0[Dcab]:d}'.format(table))
Jack: 4098; Sjoerd: 4127; Dcab: 8637678
>>> table = {'Sjoerd': 4127, 'Jack': 4098, 'Dcab': 8637678}
>>> print 'Jack: {Jack:d}; Sjoerd: {Sjoerd:d}; Dcab: {Dcab:d}'.format(**table)
Jack: 4098; Sjoerd: 4127; Dcab: 8637678
老式的字符串格式化
>>> import math
>>> print 'The value of PI is approximately %5.3f.' % math.pi
The value of PI is approximately 3.142.
读写文件
open函数打开文件并返回一个文件句柄。形如:
>>> f = open('workfile', 'w')
>>> print f
<open file 'workfile', mode 'w' at 80a0960>
关于文件的打开模式:
- r是只可读
- w是覆盖写
- a是写追加
- r+代表可读可覆盖写
- a+代表可读可追加
还有一些二进制文件的读写方式r+b,不够暂时用不上。
file对象可以通过read读取,通过readline逐行读取。
每次读取后,文件指针都会便宜,以此实现对文件的遍历。
>>> for line in f:
print line,
This is the first line of the file.
Second line of the file
读取到的字符串是包含换行符的。
如果想读取文件的全部内容,可以用:list(f) or f.readlines()。
文件写只有一个方法write。此外,通过seek函数可以偏移文件读取指针。
在文件读写完毕之后,记得close:
f.close()
读取文件无比采用下面的模型,相当于try-except:
>>> with open('workfile', 'r') as f:
... read_data = f.read()
>>> f.closed
True
JSON
Python支持JSON的编码解码。具体请看:JSON
错误和异常
如果程序运行时出错,会抛出异常,然后程序就终止了。
有的时候终止不是我们想看到的,那么可以用try-except捕获异常。形如:
>>> while True:
... try:
... x = int(raw_input("Please enter a number: "))
... break
... except ValueError:
... print "Oops! That was no valid number. Try again..."
...
下面是比较标准的异常错误处理方式:
import sys
try:
f = open('myfile.txt')
s = f.readline()
i = int(s.strip())
except IOError as e:
print "I/O error({0}): {1}".format(e.errno, e.strerror)
except ValueError:
print "Could not convert data to an integer."
except:
print "Unexpected error:", sys.exc_info()[0]
raise
raise 会把异常往上抛出,一般来说会导致程序终止。
try-except还支持结尾加else,做用是为没有定义的异常做统一的处理:
for arg in sys.argv[1:]:
try:
f = open(arg, 'r')
except IOError:
print 'cannot open', arg
else:
print arg, 'has', len(f.readlines()), 'lines'
f.close()
处理系统的异常之外,我们也可以自定义的抛出异常:
>>> try:
... raise Exception('spam', 'eggs')
... except Exception as inst:
... print type(inst) # the exception instance
... print inst.args # arguments stored in .args
... print inst # __str__ allows args to be printed directly
... x, y = inst.args
... print 'x =', x
... print 'y =', y
...
<type 'exceptions.Exception'>
('spam', 'eggs')
('spam', 'eggs')
x = spam
y = eggs
用户也能够自定义异常类
形如:
>>> class MyError(Exception):
... def __init__(self, value):
... self.value = value
... def __str__(self):
... return repr(self.value)
...
>>> try:
... raise MyError(2*2)
... except MyError as e:
... print 'My exception occurred, value:', e.value
...
My exception occurred, value: 4
>>> raise MyError('oops!')
Traceback (most recent call last):
File "<stdin>", line 1, in ?
__main__.MyError: 'oops!'
或者看这个:
class Error(Exception):
"""Base class for exceptions in this module."""
pass
class InputError(Error):
"""Exception raised for errors in the input.
Attributes:
expr -- input expression in which the error occurred
msg -- explanation of the error
"""
def __init__(self, expr, msg):
self.expr = expr
self.msg = msg
class TransitionError(Error):
"""Raised when an operation attempts a state transition that's not
allowed.
Attributes:
prev -- state at beginning of transition
next -- attempted new state
msg -- explanation of why the specific transition is not allowed
"""
def __init__(self, prev, next, msg):
self.prev = prev
self.next = next
self.msg = msg
异常清洁
就是最后加final啦:
>>> def divide(x, y):
... try:
... result = x / y
... except ZeroDivisionError:
... print "division by zero!"
... else:
... print "result is", result
... finally:
... print "executing finally clause"
...
>>> divide(2, 1)
result is 2
executing finally clause
>>> divide(2, 0)
division by zero!
executing finally clause
>>> divide("2", "1")
executing finally clause
Traceback (most recent call last):
File "<stdin>", line 1, in ?
File "<stdin>", line 3, in divide
TypeError: unsupported operand type(s) for /: 'str' and 'str'
推荐方式
下面这种方式访问文件时被推荐的,因为自带了final处理:
with open("myfile.txt") as f:
for line in f:
print line,
类
下面定义一个最简单的类:
class Complex:
def init(self, realpart, imagpart):
self.r = realpart
self.i = imagpart
x = Complex(3.0, -4.5)
x.r, x.i
(3.0, -4.5)
实例对象
这方面很像c++了,无需赘述。
方法对象
方法也是一个对象。因此可以做到赋值操作:
xf = x.f
while True:
print xf()
类和对象属性
class Dog:
kind = 'canine' # class variable shared by all instances
def __init__(self, name):
self.name = name # instance variable unique to each instance
>>> d = Dog('Fido')
>>> e = Dog('Buddy')
>>> d.kind # shared by all dogs
'canine'
>>> e.kind # shared by all dogs
'canine'
>>> d.name # unique to d
'Fido'
>>> e.name # unique to e
'Buddy'
在方法外的类属性,相当于其他语言的全局变量,这意味着,不同对象会共享这个变量(列表或者字典)
class Dog:
tricks = [] # mistaken use of a class variable
def __init__(self, name):
self.name = name
def add_trick(self, trick):
self.tricks.append(trick)
这不是一个好做法。至少在你完全掌握之前。
正确的做法是:
class Dog:
def __init__(self, name):
self.name = name
self.tricks = [] # creates a new empty list for each dog
def add_trick(self, trick):
self.tricks.append(trick)
继承
如果想要继承一个类,这样写就好了:
class DerivedClassName(modname.BaseClassName):
有下面两个函数:
- isinstance(obj, int) 将会判断obj是否为int类型
- issubclass(bool, int)将会判断是否为子类
多重继承
class DerivedClassName(Base1, Base2, Base3):
私有属性
双重下划线所标示的属性是私有属性。
异常也是类
前面讲过了
迭代器
前面看到的迭代器大多是这样的::
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,
其实有专门的iter迭代器。
>>> 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 "<stdin>", line 1, in ?
it.next()
StopIteration
生成器
一个例子
def reverse(data):
for index in range(len(data)-1, -1, -1):
yield data[index]
for char in reverse('golf'):
print char
生成器表达式
很有用,但是可读性比较差。