入门

变量和基础类型

数据类型

  • 整数 十六进制:0x
  • 浮点数 1.23e4
  • 字符串 ‘xxx’ 或 “xxx”
  • 布尔值 True、False and、or、not
  • 空值 None(不能理解为0)

print

1
2
print '1 + 2=', 1 + 2    # 1 + 2 = 3  结束后自动换行
print 'hello' , 'world' # 逗号会输出一个空格

变量

大小写英文、数字、下划线,且不能是数字开头

1
2
3
a = 1
t_007 = 'T007'
a == 1 # 相等

变量本身类型不固定的语言称之为动态语言,与之对应的是静态语言。

字符串

####常见字符串

如果字符串包含单引号',则要用双引号""括起来

如果既包含单引号又包含双引号,就要用反斜杠\来转义

####raw字符串

如果一个字符串有很多要转义的字符,可以加个前缀r,表示这是一个raw字符串,里面的字符就不需要转义了。例如:

1
r'\(~_~)/ \(~_~)/'

但是r'...'表示法不能表示多行字符串,也不能表示包含'"的字符串

####多行字符串

如果要表示多行字符串,可以用'''...'''表示(同样可以在前面加一个r):

1
2
3
'''Line 1
Line 2
Line 3'''

上面这个字符串的表示方法和下面的是完全一样的:

1
'Line 1\nLine 2\nLine 3'

Unicode字符串

最早的Python只支持ASCII编码,普通的字符串’ABC’在Python内部都是ASCII编码的。

Python在后来添加了对Unicode的支持,以Unicode表示的字符串用u’…’表示,比如:

1
print u'中文'  # 中文

注意: 不加 u ,中文就不能正常显示。

除了多了一个u之外,与普通字符串没啥区别,转义字符和多行表示法仍然有效

如果中文字符串在Python环境下遇到 UnicodeDecodeError,这是因为.py文件保存的格式有问题。可以在第一行添加注释

1
# -*- coding: utf-8 -*-

整数与浮点数

同C语言:

  • 整数 + 浮点数 = 浮点数
  • 整数 / 整数 = 整数
  • 整数 / 浮点数 = 浮点数

List 与 Tuple 类型

###list

1
2
3
classmates = ['Michael', 'Bob', 'Tracy']
L = ['Michael', 100, True]
empty_list = []

####倒序访问

1
2
print L[0]  # 索引从 0 开始
print L[-1] # 倒序访问最后一个元素(也注意不要越界)

添加元素

1
2
L.append('Paul')  # 添加到尾部
L.insert(0, 'Paul') # 添加到开头

删除元素

1
2
L.pop()  # 删除最后一个并返回这个元素
L.pop(2) # 删除第三个元素

替换元素

1
L[-1] = 'Paul'

字符串list 首字母大写

1
2
c = ['zz','yy','xx'] 
c = [string.capitalize() for string in c]

tuple

即不可变的 list

1
t = ()  # 空tuple
1
2
3
t = ('Adam', 'Lisa', 'Bart')
a = t[-2]
# t[1] = 'Bob' # 报错

tuple和list外观唯一不同之处是用( )替代了[ ]

tuple没有 append()方法,也没有insert()和pop()方法

####单元素tuple

1
t = (1)  # 这是整数 1,而不是tuple
1
2
t = (1,)  # 可以加一个逗号","避免歧义
print t # (1,)

多元素 tuple 加不加这个额外的“,”效果是一样的:

1
2
t = (1, 2, 3,)
print t # (1, 2, 3)

“可变”的 tuple

1
2
3
4
t = ('a', 'b', ['A', 'B'])
L = t[2]
L[0] = 'X'
print t # ('a', 'b', ['X', 'Y'])

tuple所谓的“不变”是说,tuple的每个元素,指向永远不变。即指向’a’,就不能改成指向’b’,指向一个list,就不能改成指向其他对象,但指向的这个list本身是可变的!

条件判断与循环

if - elif - else

if 语句后接表达式,然后用:表示代码块开始。

注意: elif 和 else 后面有个 “:

1
2
3
4
5
6
7
8
9
age = 20
if age >= 18:
print 'your age is', age
print 'adult'
elif age > 10:
print 10
else:
print age
print 'END'

注意: **Python代码的缩进规则**。具有相同缩进的代码被视为代码块

缩进请严格按照Python的习惯写法:4个空格不要使用Tab,更不要混合Tab和空格,否则很容易造成因为缩进引起的语法错误。

如果你在Python交互环境下敲代码,还要特别留意缩进,并且退出缩进需要多敲一行回车

循环

1
2
3
L = ['Adam', 'Lisa', 'Bart']
for name in L:
print name
1
2
3
4
5
N = 10
x = 0
while x < N:
print x
x = x + 1

循环控制

  • break
  • continue

Dict 和 Set 类型

###Dict

{ key : value }

1
2
3
4
5
6
7
8
9
d = {
'Adam': 95,
'Lisa': 85,
'Bart': 59
}
print d # 注意:乱序存储,不会按顺序输出(和 list 不一样)
len(d) # 3 len()用来求任意集合的大小
print d['Adam'] # 95
# print d['Paul'] # 报错:KeyError

判断 key 是否存在:

1
2
if 'Paul' in d:
print d['Paul']

dict 的 get 方法:在 Key 不存在的时候返回 None

1
2
print d.get('Bart')  # 59
print d.get('Paul') # None

Dict 的特点

dict的第一个特点是查找速度快,无论dict有10个元素还是10万个元素,查找速度都一样

dict的缺点是占用内存大,还会浪费很多内容,list正好相反,占用内存小,但是查找速度慢。

由于dict是按 key 查找,所以,在一个dict中,key不能重复。

dict的第二个特点就是存储的key-value序对是没有顺序的!这和list不一样

打印的顺序不一定是我们创建时的顺序

dict的第三个特点是作为 key 的元素必须不可变:可变的 list 不能作为 key

1
2
3
4
{
'123': [1, 2, 3], # key 是 str,value是list
('a', 'b'): True # key 是 tuple,并且tuple的每个元素都是不可变对象,value是 boolean
}

更新 dict

1
d['Paul'] = 72

如果 key 已经存在,则赋值会用新的 value 替换掉原来的 value

####遍历 dict

1
2
3
d = { 'Adam': 95, 'Lisa': 85, 'Bart': 59 }
for key in d:
print key, d[key] # Lisa 95 \n...

set

dict的作用是建立一组 key 和一组 value 的映射关系,dict的key是不能重复的。

set 持有一系列元素,这一点和 list 很像,但是set的元素没有重复,而且是无序的,这点和 dict 的 key很像。

创建 set 的方式是调用 set() 并传入一个 list,list的元素将作为set的元素:

1
2
s = set(['A', 'B', 'C', 'A'])
print s # set(['A', 'C', 'B']) 和 dict 一样是 乱序打印

####访问 set

1
2
3
s = set(['Adam', 'Lisa', 'Bart', 'Paul'])
'Bart' in s # True
'bart' in s # False (注意大小写)

set 的特点

key必须是不变对象

判断一个元素是否在set中速度很快

set存储的元素也是没有顺序的

遍历 set

1
2
3
s = set(['Adam', 'Lisa', 'Bart'])
for name in s:
print name # 注意:打印的顺序很可能是不同的

更新 set

1
2
s.add('Adam')  # 如果添加的元素已经存在,不会报错,但是不会加进去了
s.remove(4) # 删除 值为4 的元素。如果元素不存在,会报错(删除前要先判断)

函数

内置函数

1
2
3
4
5
int('123')  # 转换到整数
str(10) # 到字符串
abs(10.1)
sqrt(100) # math 包下
help(abs) # 查看abs的帮助信息

自定义函数

1
2
3
4
5
def my_abs(x):
if x >= 0:
return x # 执行完毕,不继续下去
else:
return -x

return None可以简写为return

多返回值

1
2
3
4
5
6
7
8
import math
def move(x, y, step, angle):
nx = x + step * math.cos(angle)
ny = y - step * math.sin(angle)
return nx, ny

x, y = move(100, 100, 60, math.pi / 6)
print x, y # 151.961524227 70.0

但其实这只是一种假象,Python函数返回的仍然是单一值
用print打印返回结果,原来返回值是一个tuple
在语法上,返回一个tuple可以省略括号,而多个变量可以同时接收一个tuple,按位置赋给对应的值

递归函数

1
2
3
4
5
6
def fact(n):
if n==1:
return 1
return n * fact(n - 1)

fact(5) # 120

使用递归函数需要注意防止栈溢出

默认参数

1
int('123', 8)  # 83  两个参数的int:10进制转到8进制
1
2
3
4
5
6
7
8
def power(x, n=2):  # 求幂,默认平方
s = 1
while n > 0:
n = n - 1
s = s * x
return s

power(5) # 25

由于函数的参数按从左到右的顺序匹配,所以默认参数只能定义在必需参数的后面

可变参数

1
2
def fn(*args):
print args

可变参数的名字前面有个 *** **号

解释器会把传入的一组参数组装成一个tuple传递给可变参数,直接把变量 args 看成一个 tuple 就好了

切片

对list进行切片

1
2
L[0:3]  # 取前3个元素:['Adam', 'Lisa', 'Bart']
L[1:3] # 取 第2、3、4个元素

L[0:3]表示,从索引0开始取,直到索引3为止,但不包括索引3。即索引0,1,2,正好是3个元素。

如果第一个索引是0,还可以省略:

1
2
L[:3]  # 前三个
L[:] # 表示从头到尾,实际上复制出了一个新list

切片操作还可以指定第三个参数:

1
L[::2]  # 表示每N个取一个

把list换成tuple,切片操作完全相同,只是切片的结果也变成了tuple。

倒序切片

1
2
3
4
5
L = ['Adam', 'Lisa', 'Bart', 'Paul']
L[-2:] # 倒数第二个直到结尾(最后两个) ['Bart', 'Paul']
L[:-2] # 开头直到最后第二个(但不包括) ['Adam', 'Lisa']
L[-3:-1] # 倒数第三个直到倒数第一个(不包括) ['Lisa', 'Bart']
L[-4:-1:2] # -4、-2 ['Adam', 'Bart']

记住倒数第一个元素的索引是-1。倒序切片包含起始索引,不包含结束索引。

字符串切片

1
2
3
'ABCDEFG'[:3]  # 'ABC'
'ABCDEFG'[-3:] # 'EFG'
'ABCDEFG'[::2] # 'ACEG'
1
2
3
4
5
6
7
'abc'.upper()  # 所有字母变大写 'ABC'

# 单词首字母大写函数
def firstCharUpper(s):
return s[0].upper() + s[1:]

print firstCharUpper('hello') # Hello

迭代

就是遍历

Python 的 for循环不仅可以用在list或tuple上,还可以作用在其他任何可迭代对象上

索引迭代

在 for 循环中拿到索引:enumerate() 函数 ,绑定索引index和元素name

1
2
3
L = ['Adam', 'Lisa', 'Bart', 'Paul']
for index, name in enumerate(L):
print index, '-', name

输出结果是:

1
2
3
4
0 - Adam
1 - Lisa
2 - Bart
3 - Paul

实际上,enumerate() 函数把:

1
['Adam', 'Lisa', 'Bart', 'Paul']

变成了类似:

1
[(0, 'Adam'), (1, 'Lisa'), (2, 'Bart'), (3, 'Paul')]

因此,迭代的每一个元素实际上是一个tuple:

1
2
3
4
for t in enumerate(L):
index = t[0]
name = t[1]
print index, '-', name

如果我们知道每个tuple元素都包含两个元素,for循环又可以进一步简写为:

1
2
for index, name in enumerate(L):  # 最初的式子
print index, '-', name

额外:zip()函数

zip()函数可以把两个 list 变成一个 list:

1
2
zip([10, 20, 30], ['A', 'B', 'C'])
# [(10, 'A'), (20, 'B'), (30, 'C')]

迭代dict的value

dict 对象有一个 values() 方法:把dict转换成一个包含所有value的list,这样,我们迭代的就是 dict的每一个 value:

1
2
3
4
5
6
7
8
d = { 'Adam': 95, 'Lisa': 85, 'Bart': 59 }
print d.values()
# [85, 95, 59]
for v in d.values():
print v
# 85
# 95
# 59

dict除了values()方法外,还有一个itervalues() **方法,用itervalues()** 方法替代 values() 方法,迭代效果完全一样:

1
2
3
4
5
6
7
8
d = { 'Adam': 95, 'Lisa': 85, 'Bart': 59 }
print d.itervalues()
# <dictionary-valueiterator object at 0x106adbb50>
for v in d.itervalues():
print v
# 85
# 95
# 59

那这两个方法有何不同之处呢?

  1. values() 方法实际上把一个 dict 转换成了包含 value 的list。

  2. 但是 itervalues() 方法不会转换,它会在迭代过程中依次从 dict 中取出 value,所以 itervalues() 方法比 values() 方法节省了生成 list 所需的内存。

  3. 打印 itervalues() 发现它返回一个 <dictionary-valueiterator> 对象,这说明在Python中,for 循环可作用的迭代对象远不止 list,tuple,str,unicode,dict等,任何可迭代对象都可以作用于for循环,而内部如何迭代我们通常并不用关心。

如果一个对象说自己可迭代,那我们就直接用 for 循环去迭代它,可见,迭代是一种抽象的数据操作,它不对迭代对象内部的数据有任何要求。

迭代dict的key和value

1
2
d = { 'Adam': 95, 'Lisa': 85, 'Bart': 59 }
print d.items() # [('Lisa', 85), ('Adam', 95), ('Bart', 59)]
1
2
3
4
5
6
for key, value in d.items():
print key, ':', value

# Lisa : 85
# Adam : 95
# Bart : 59

和 values() 有一个 itervalues() 类似, items() *也有一个对应的 *iteritems(),iteritems() 不把dict转换成list,而是在迭代过程中不断给出 tuple,所以, iteritems() 不占用额外的内存。

列表生成式

生成列表

1
2
# 生成list [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
range(1, 11) # [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
1
2
3
4
5
6
# 生成[1x1, 2x2, 3x3, ..., 10x10] (方式一:循环)(繁琐)
L = []
for x in range(1, 11):
L.append(x * x)

L # [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
1
2
3
# 生成[1x1, 2x2, 3x3, ..., 10x10] (方式二:列表生成式)
[x * x for x in range(1, 11)]
# [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

复杂表达式

假设有如下的dict:

1
d = { 'Adam': 95, 'Lisa': 85, 'Bart': 59 }

完全可以通过一个复杂的列表生成式把它变成一个 HTML 表格:

1
2
3
4
5
tds = ['<tr><td>%s</td><td>%s</td></tr>' % (name, score) for name, score in d.iteritems()]
print '<table>'
print '<tr><th>Name</th><th>Score</th><tr>'
print '\n'.join(tds)
print '</table>'

注:字符串可以通过 % 进行格式化,用指定的参数替代%s。字符串的join()方法可以把一个 list 拼接成一个字符串。

条件过滤

for 循环后面可以加上 if 判断

1
2
[x * x for x in range(1, 11) if x % 2 == 0]
# [4, 16, 36, 64, 100]

有了 if 条件,只有 if 判断为 True 的时候,才把循环的当前元素添加到列表中。

多层表达式

对于字符串 ‘ABC’ 和 ‘123’,可以使用两层循环,生成全排列:

1
2
>>> [m + n for m in 'ABC' for n in '123']
['A1', 'A2', 'A3', 'B1', 'B2', 'B3', 'C1', 'C2', 'C3']

翻译成循环代码就像下面这样:

1
2
3
4
L = []
for m in 'ABC':
for n in '123':
L.append(m + n)