初学Python

Python的数据类型

  1. 整数 整数的运算结果是精确的
  2. 浮点数 浮点数的运算结果不一定是精确的,可能有精度损失。整数和浮点数一起运算结果为浮点数。
  3. 字符串 用’’或””括起来的任意文本。

    1. 如果字符串中有’可以用””括起来。 例如:”aaa ‘bbb’ aaa”
    2. 如果字符串中有”可以用’’括起来。 例如:’aaa “bbb” aaa’
    3. 如果字符串中既有’又有”,可以用\转义。 例如:"aaa \'bbb\'\"ccc\" aaa"'aaa \'bbb\'\"ccc\" aaa'
    4. 如果字符串中存在多个需要转义的字符,对每个字符都转义很麻烦,可以在字符串前加前缀r,表示一个raw字符串,里面的字符就不需要转义啦。 例如:r'\(~_~)/ \(~_~)/' 但r’…’表示法不能表示多行字符串,也不能表示包含’和”的字符串。
    5. 如果要表示多行字符串,可以用'''...'''表示。 例如

      1
      2
      3
      ''' Line1
      Line2
      Line3'''
    6. 可以在多行字符串前加r前缀,将其变为raw字符串。

  4. 布尔值 True、False 运算:与(and)、或(or)、非(not) Python将0、空字符串、None看作False,其它数值和非空字符串都看成True。and和or短路计算。
  5. 空值 None None不能理解为0,因为0是有意义的,而None是一个特殊的空值。

Python的注释以#开头

Python变量

Python标识符必须是大小写英文、数字和下划线的组合,且不能数字开头。不能使保留字。区分大小写。
Python是动态语言。可以把任意数据类型赋值给变量,同一个变量可以反复赋值,而且可以是不同类型的变量。
Python3关键字

Python中Unicode字符串需要在字符串前加多u前缀。

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

告诉Python解释器,用UTF-8编码读取源代码。文件格式也要保存为UTF-8格式。

Python创建list

list是一种有序的集合,可以随时添加和删除其中元素。构造list直接用[]将list的所有元素都括起来,就是list对象。list中包含的元素可以是不同的数据类型。一个元素都没有的list就是空list。
list可以通过索引获取指定元素。索引从0开始。使用索引访问list注意不要越界,超过索引范围会报错。
list可以用-1访问最后一个元素。-n表示倒数第n个,注意不要越界。

Python中list添加新元素

  1. 使用list的append()方法。append将新元素添加到list的尾部。
  2. 使用list的insert()方法,insert接受两个参数,第一个是索引号,第二个是待添加的新元素,表示将新元素插入到索引号所在的位置,原有元素后移。

Python中list删除元素

  1. 使用list的pop()方法。pop方法不带参数,删除并返回list的最后一个元素。
  2. 使用list的pop()方法。pop方法带一个索引号参数,删除并返回索引号所在位置的元素,后面的元素前移。

Python替换元素

对list的某个索引赋值,直接用新元素替换原来的元素。

Python创建tuple

元组一旦创建完毕就不能修改了。创建元组使用()将tuple的所有元素都括起来。tuple可以使用索引访问元素。
Python创建单元素tuple,()可以表示tuple,也可以作为括号表示运算时的优先级。

1
2
3
4
# 错误,t不是tuple,而是整数1 (1)会被Python解释器计算出结果1
t = (1)
# 正确
t = (1,)

Python条件判断和循环

Python具有相同缩进的代码被视为代码块。缩进习惯:4个空格,不要使用Tab,更不要使用Tab和空格。

if语句

1
2
if 判断语句 :
代码块

if-else语句

1
2
3
4
if 判断语句 :
代码块
else :
代码块

if-elif-else

1
2
3
4
5
6
if 判断条件 :
代码块
elif 判断条件 :
代码块
else :
代码块

不能忘记”:”号

for循环

1
2
3
4
5
6
7
8
9
10
11
for 临时变量 in 要遍历的容器
代码块

L = [1, 2, 3, 4,]
for num in L
print num

for 临时变量 in 要遍历的容器
代码块
else : # 循环结束 则会执行下面的代码块 如果循环被break打断,则不会执行
代码块

while循环

1
2
3
4
5
6
7
8
9
10
11
12
13
while 判断条件 :
代码块

N = 10
x = 0
while x < N :
print x
x = x + 1

while 判断条件 :
代码块
else : # 循环结束 则会执行下面的代码块 如果循环被break打断,则不会执行
代码块

while循环每次先判断判断条件,如果为True,则继续执行循环体的代码块,否则,退出循环。

break退出循环

用 for 循环或者 while 循环时,如果要在循环体内直接退出循环,可以使用 break 语句。

continue退出本次循环,继续循环

在循环过程中,可以用break退出当前循环,还可以用continue跳过后续循环代码,继续下一次循环。

Python的循环可以嵌套

for循环比while循环执行速度快

Python提供两个内置函数用于在for循环中定制特殊的循环

  1. range或xrange range一次性地返回连续的整数列表 xrange一次产生一个数据元素,相较于range更节约空间
  2. zip 返回并行的元素元组的列表,常用于在for循环中遍历数个序列

Python中dict的创建

dict用来存储键值对。
花括号{}表示一个dict,然后按照key:value,将元素填入。

1
2
3
4
5
6
7
8
9
10
{
键 : 值,
......
}

{
'key1' : value1,
'key2' : value2,
'key3' : value3,
}

len()函数可以计算任意集合的大小。dict、list、tuple都是集合。

Python中dict的访问

可以是通过key访问dict的value,只要key存在,dict返回对应的value。如果key不存在,直接报错:KeyError。
避免KeyError的两种方法:

  1. 线判断Key是否存在,用in操作符
  2. 使用dict提供的get方法,在Key不存在时,返回None
1
2
3
4
5
6
7
8
9
10
11
12
d = {
'key1': 1
'key2': 2
}

if 'key1' in d:
print d['key1']
if 'key3' in d:
print d['key3']

print d.get('key1')
print d.get('key3')

Python中dict的特点

  1. dict查找速度快,查找速度不会随着元素数量增多而变慢。list的查找速度回随着元素增多而逐渐下降。
  2. dict的key不可重复。
  3. dict存储的key-value是没有顺序的。
  4. dict作为key的元素必须不可变。

Python更新dict

添加新的键值对,如果key已经存在则会替换掉原来的value

1
2
3
d = { 'key1' : 1, 'key2' : 2, }
d['key3'] = 3
d['key3'] = 6

Python遍历dict

通过for循环可以遍历dict的key,通过key获取value。

1
2
3
d = { 'key1' : 1, 'key2' : 2, }
for key in d :
print key

Python中set的创建

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

1
2
s = set(['A', 'B', 'C',])
print s

Python中set的访问

set存储的无序集合,无法通过索引访问。访问一个set中的某个元素实际上就是判断该元素是否存在于set中。可以用in操作符判断。

1
2
3
s = set(['A', 'B', 'C',])
print 'A' in s
print 'D' in s

Python中set的特点

  1. 访问速度快
  2. set存储的元素不可变
  3. set存储元素没有顺序

Python中set的遍历

通过for循环遍历

1
2
3
s = set(['A', 'B', 'C',])
for value in s :
print value

Python更新set

给set添加元素,使用set提供的add()方法
从set中删除元素,使用set提供的remove()方法。如果remove的元素不存在,remove会报错,所有remove前需要判断。

Python函数

Python中定义一个函数要使用def语句,依次写出函数名、括号、括号中的参数和冒号,然后,在缩进块中编写函数体,函数的返回值用return语句返回。
如果没有return语句,函数执行完毕也会返回结果,只是结果为None。
return None可以简写为return。

1
2
3
4
5
def my_abs(x)
if x >= 0 :
return x
else :
return -x

Python函数可以返回多个返回值

Python函数返回多个值,其返回值其实是一个tuple。在语法上,返回一个tuple可以省略括号,而多个变量可以同时接收一个tuple,按位置赋给对应的值,所以,Python的函数返回多值其实就是返回一个tuple。

Python函数调用可以递归调用自身

递归函数的优点是定义简单,逻辑清晰。理论上,所有的递归函数都可以写成循环的方式,但循环的逻辑不如递归清晰。
使用递归函数需要注意防止栈溢出。在计算机中,函数调用是通过栈(stack)这种数据结构实现的,每当进入一个函数调用,栈就会加一层栈帧,每当函数返回,栈就会减一层栈帧。由于栈的大小不是无限的,所以,递归调用的次数过多,会导致栈溢出。

1
2
3
4
5
6
7
8
9
10
def move(n, a, b, c):
if n==1 :
print a, '-->', c
return

move(n-1, a, c, b)
print a, '-->', c
move(n-1, b, a, c)

move(4, 'A', 'B', 'C')

递归需要边界条件,递归前进段和递归返回段

Python函数定义默认参数

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

1
2
3
4
5
6
def power(x, n=2)
s = 1
while n > 0 :
n = n - 1
s = s * x
return s

Python定义可变参数

可变参数让一个函数可以接受任意个参数。

1
2
def fn(*args) :
pirnt args

可变参数的名字前加*号,可以传入0个、1个或多个参数给可变参数。传入可变参数,实质是传入了一个tuple。

Python函数内使用全局变量,需要使用global关键字声明

1
2
3
4
5
6
7
8
9
x = 32
print x # 32
def f1():
global x
x = 43
print x # 43

f1()
print x # 43

Python 参数传递形式

位置参数:从左到右
关键字参数:按关键名称匹配
既有位置参数,又有关键词参数时:所有位置参数,所有关键字参数
定义函数时使用默认参数:有默认值的参数
混用有默认和无默认值的参数对,无默认值在前
调用函数时使用可变参数要求:
定义函数时使用*,收集位置参数
定义函数时使用**,收集关键字参数

Python对list进行切片

对于经常取指定索引范围的操作,Python提供切片(Slice)操作符。

1
2
3
L = [1, 2, 3, 4, 5, 6, 7, 8, 9,]
L[0:3] #从索引0开始到索引3为止 1 2 3
L[:3] #与L[0:3]左右相同

切片操作实质是复制出一个新的list
切片操作还可以指定第三个参数,表示每N个取一个。

1
2
L = [1, 2, 3, 4, 5, 6, 7, 8, 9,]
L[0:6:2] #从索引0开始到索引6结束,每2个取一个,即隔一个取一个。

把list换成tuple,切片操作完全相同,只是切片的结果也变成了tuple。
list支持L[-1]取倒数第一个元素,同样支持倒数切片。倒数第一个元素的索引是-1。倒序切片包含起始索引,不包含结束索引。
字符串也支持切片操作,操作结果是字符串。Python没有对字符串的截取函数。

Python迭代

在Python中迭代通过for…in来完成。
Python迭代操作是对于一个集合,无论该集合是有序或者无序,用for循环总是可以依次取出集合的每一个元素。
集合:

  1. 有序集合:list、tuple、str和unicode
  2. 无序集合:set
  3. 无序集合并且具有key-value对:dict

迭代是一个动词,指一种操作,在python中就是for循环。迭代与按下标访问数组最大的不同是,后者是一种具体的迭代实现方式,前者只关心迭代结果,不关心迭代内部的具体实现。

Python索引迭代

Python中迭代永远是取出元素本身,而非元素的索引。
如果想在for循环中拿到索引,可以使用enumerate()函数。enumerate将迭代的每个元素实际是一个tuple。

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

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

Python迭代dict

用for直接迭代dict可以得到dict的key,如果想迭代dict对象的value,可以使用dict对象的values()方法,该方法将dict转换成包含所有value的list。dict提供的itervalues方法可以替代value方法,迭代效果完全一样。

  1. values()方法实际把一个dict转换成包含value的list。
  2. itervalues()方法不会转换,在迭代过程中依次从dict中取出value,itervalues方法比values方法节省内存。

如果迭代dict时即想得到key,又想得到value,可以使用dict对象的items()方法返回的值。该方法将dict转化为包含tuple的list。通过对该list的迭代得到key和value。

Python迭代

iterator(可迭代)对象
支持每次返回自己包含的一个成员的对象
对象实现__iter__方法 序列类型 非序列类型 用户自定义包含__iter__()__getitem__()方法的类

Python生成列表

  1. range()
  2. 列表生成式
  3. 字符串可以通过 % 进行格式化,用指定的参数替代 %s。字符串的join()方法可以把一个 list 拼接成一个字符串。
  4. 条件过滤,列表生成式的for循环后面可以加上if判断。
  5. 列表表达式多层for循环可以嵌套。
1
2
3
4
5
6
7
8
# [1x1, 2x2, 3x3, ..., 10x10]
[x * x for x in range(1, 11)]

# 获得偶数的平方
[x * x for x in range(1, 11) if x % 2 == 0]

# 利用 3 层for循环的列表生成式,找出对称的 3 位数。例如,121 就是对称数,因为从右到左倒过来还是 121。
[n1*100+n2*10+n3 for n1 in range(1,10) for n2 in range(10) for n3 in range(10) if n1==n3]

Python列表解析

Python列表解析是Python迭代机制的一种应用,常用于创建新的列表,因此放置在[]中。
语法:

1
2
[expression for iter_var in iterable]
[expression for iter_var in iterable if cond_expr]

Python生成器表达式

生成器表达式并不真正创建数字列表,而是返回一个生成器对象,此对象在每次计算出一个条目后,把这个条目”产生”(yield)出来。生成器表达式使用惰性计算或称为延迟求值的机制。
序列过长,并且每次只需要获取一个元素时,应当考虑使用生成器表达式而不是列表解析
语法:

1
2
(expr for iter_var in iterable)
(expr for iter_var in iterable if cond_expr)

高阶函数

函数名就是指向函数的变量。
高阶函数:能接收函数作为参数的函数。

map()

map()函数是Python内置的高阶函数,接受一个函数f和一个list,并通过把函数f依次作用于list的每个元素上,得到新的list并返回。map()不会改变原有的list,而是返回一个新的list。

reduce()

reduce()函数是Python内置的高阶函数,接受一个函数f和一个list,函数f必须接受两个参数,reduce()对list的每个元素重复调用函数f,并返回最终结果值。reduce()可以接受第三个可选参数,作为计算的初值。

1
2
3
4
5
def f(x, y)
return x + y

reduce(f, [1, 3, 5, 7]) # f(1, 3) f(4, 5) f(9, 7) 返回最终结果16
reduce(f, [1, 3, 5, 7], 100) # 最终结果116

filter()

filter()函数是Python内置的高阶函数,接受一个函数f和一个list,函数f的作用是对每个元素进行判断,返回True或False,filter()根据判断结果自动过滤不符合条件的元素,返回由符合条件元素组成的新list。

1
2
3
4
# 从一个list [1, 4, 6, 7, 9, 12, 17]中删除偶数,保留奇数
def is_odd(x):
return x % 2 == 1
filter(is_odd, [1, 4, 6, 7, 9, 12, 17])

sorted()

Python内置sorted()函数可以对list进行排序。
sorted()函数也是一个高阶函数,可以接收一个函数来实现自定义排序,比较函数定义是,传入两个待比较的元素x、y,如果x应该排在y的前面,返回-1,如果x应该排在y的后面,返回1,如果x和y相等,返回0。

1
2
3
4
5
6
7
8
9
print sorted([36, 5, 12, 9, 21])
def reversed_cmp(x, y):
if x > y:
return -1
if x < y:
return 1
return 0

print sorted([36, 5, 12, 9, 21], reversed_cmp)

Python中返回函数

Python的函数不但可以返回int、str、list、dict等数据类型,还可以返回函数。

1
2
3
4
5
6
7
8
9
10
def f():
print 'call f()...'
# 定义函数g:
def g():
print 'call g()...'
# 返回函数g:
return g

x = f()
x() #会调用g()

返回函数可以把一些计算延迟执行。

Python闭包

在函数内部定义的函数和外部定义的函数是一样的,只是无法被外部访问。
如果内层函数引用了外层函数的变量(参数也算变量),然后返回内层函数的情况,称为闭包(Closure)。
外层函数提供了内层函数的环境
闭包的特点是返回的函数还引用了外层函数的局部变量,所以,要正确使用闭包,就要确保引用的局部变量在函数返回后不能变。返回函数不要引用任何循环变量,或者后续会发生变化的变量。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
def count():
fs = []
for i in range(1, 4):
def f():
return i*i
fs.append(f)
return fs
f1, f2, f3 = count()
print f1(), f2(), f3() # 9, 9, 9

def count():
fs = []
for i in range(1, 4):
def f(j): # 加多一层,保存临时变量的值 后续不会再变化
def g():
return j*j
return g
r = f(i)
fs.append(r)
return fs
f1, f2, f3 = count()
print f1(), f2(), f3() # 1, 4, 9

Python匿名函数

lambda args: expression

  1. args:用逗号分隔的参数列表
  2. expression:表达式

Python对匿名函数提供了有限支持。匿名函数有个限制,就是只能有一个表达式,不能是别的非表达式语句,不写return,返回值就是该表达式的结果。使用匿名函数,可以不必定义函数名,直接创建一个函数对象。关键字lambda 表示匿名函数,冒号前面的 x 表示函数参数。

1
2
3
4
5
map(lambda x: x * x, [1, 2, 3, 4, 5, 6, 7, 8, 9])

# lambda x: x*x 实际就是:
def f(x):
return x*x

返回函数的时候也可以返回匿名函数。
lambda的首要用途是指定短小的回调函数
lambda将返回一个函数而不是将函数赋值给某个变量名
lambda是一个表达式而非语句
lambda是一个单个表达式,而不是一个代码块
lambda也支持默认参数

Python装饰器

Python内置的@语法简化装饰器调用。
装饰器简化代码,避免每个函数编写重复性代码。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
def f1(x):
return x*2

def new_fn(f):
def fn(x):
print 'call' + f.__name__ + '()'
return f(x)
retun fn

g1 = new_fn(f1)
print g1(5)

f1 = new_fn(f1) # 彻底隐藏原函数
print f1(5)

@new_fn
def f2(x):
return x*3
# 等同于
def f2(x):
return x*3
f2 = new_fn(f2)

python中编写无参数decorator

Python中的decorator本质上是一个高阶函数,接受一个函数作为参数,返回一个新的函数。使用decorator用Python提供的@语法,简化decorator的书写。
利用Python的*args**kw,保证任意个数的参数总是能正常调用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
def log(f):
def fn(x):
print 'call ' + f.__name__ + '()...'
return f(x)
return fn

@log
def factorial(n):
return reduce(lambda x,y: x*y, range(1, n+1))
print factorial(10) #正常

@log
def add(x, y):
return x + y
print add(1, 2) #错误,参数不是一个

def log(f):
def fn(*args, **kw): #保证任意个数的参数总是能正常调用。
print 'call ' + f.__name__ + '()...'
return f(*args, **kw)
return fn

python中编写带参数的decorator

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
def log(prefix):
def log_decorator(f):
def wrapper(*args, **kw):
print '[%s] %s()...' % (prefix, f.__name__)
return f(*args, **kw)
return wrapper
return log_decorator

@log('DEBUG')
def test():
pass
print test()

#拆开看
def test():
pass

test = log('DEBUG')(test)
#再展开
log_decorator = log('DEBUG')
test = log_decorator(test)

# 又相当于
log_decorator = log('DEBUG')
@log_decorator
def test():
pass

Python中完善decorator

用Python内置的functools可将原函数的属性复制到新函数。但原函数的原始参数信息无法获得。

Python中偏函数

当一个函数有很多参数时,调用者就需要提供多个参数。如果减少参数个数,就可以简化调用者的负担。
functools.partial可以把一个参数多的函数变成一个参数少的新函数,少的参数需要在创建时指定默认值。

1
2
3
4
5
def int2(x, base=2):
return int(x, base)

int2 = functools.partial(int, base=2)
int2('1000000')

Python yield与生成器

1
2
3
4
5
6
7
8
9
def getNum(x)
y = 0
while y<=x:
yield y
y += 1

g1 = getNum(10)
print g1.next()
print g1.next()

函数中使用yield会生成一个生成器对象

Python包和模块

包:包是一个有层次的文件目录结构,定义了由n个模块或n个子包组成的Python应用程序执行环境。包是一个包含init.py 文件的目录,该目录下一定得有这个init.py文件和其它模块或子包。
模块:在Python可理解为对应于一个文件。

Python之导入模块

要使用一个模块,必须首先导入该模块。Python使用import语句导入一个模块。
如果只希望导入某个模块的某几个函数,使用from import。

1
2
import math # 导入整个math模块
from math import pow, sin, log # 导入math模块pow() sin() log()函数

如果使用import导入模块,必须通过模块名引用函数名。
通过from import导入可能会出现名字冲突,可利用别名解决。

1
2
3
4
from math import log
from logging import log as logger # logging的log有个logger的别名
print log(10) # 调用的math的log
logger(10, 'import from logging') # 调用的是logging的log

Python动态导入模块

如果导入的模块不存在,Python解释器会报ImportError错误。
因为Python是动态语言,解释执行,因此Python代码运行速度慢。

1
2
3
4
5
try:
from cStringIO import StringIO
excerpt ImportError:
from StringIO import StringIO
# StringIO 和 cStringIO 都提供StringIO功能,StringIO 是纯Python代码编写的,而 cStringIO 部分函数是 C 写的,因此 cStringIO 运行速度更快。先尝试从cStringIO导入,如果失败了,再尝试从StringIO导入。

import和from都是隐性赋值语句,import将整个模块对象赋值给一个变量名,from将一个或多个变量名赋值给导入此模块的模块中的同名对象

import工作机制

  1. 查找模块文件,在指定路径下搜索模块文件
    1. 程序主目录
    2. PYTHONPATH目录(如果设置了)
    3. 标准链接库目录
    4. 任何.pth文件的内容(如果存在.pth文件)
  2. 编译为字节码,当文件导入时会编译,顶层文件的.pyc字节码文件在内部使用后会被丢弃,只有被导入文件才会留下.pyc文件
  3. 执行模块的代码创建其所定义的对象,模块文件的所有语句依次执行,从头到尾,而此步骤中任何对变量名的赋值运算,都会所得到的模块文件的属性

模块只在第一次导入时执行如上步骤,后续的导入操作只不过是提取内存中已加载的模块对象,reload()可用于重新加载模块。

Python future

当新版本的一个特性与旧版本不兼容时,该特性将会在旧版本中添加到future中,以便旧的代码能在旧版本中测试新特性。

Python按照第三方模块 使用pip

Python包

包将一组模块归并到一个目录中,此目录即为包,目录名即为包名。包是一个有层次的文件目录结构,定义了一个由模块和子包组成的Python应用程序执行环境。基于包,Python在执行导入模块时,可以指定模块的导入路径。
包导入语句的路径内的每个目录内必须有__init__.py文件,__init__.py可包含Python代码,但通常为空,仅用于扮演包初始化的挂钩、替目录产生模块命名空间以及使用目录导入时实现from *行为的角色。

Python distutils发布模块

distutils模块能帮助完成模块或程序发布。
创建发布,将个代码文件组织到模块容器中,准备README或README.txt文件,在容器中创建setup.py文件
setup.py示例
setup.py属性
属性大体分为两类:元数据信息和包中的内容列表

1
python setup.py sdist

可以为sdist指定格式: —formats

  1. zip: zip file
  2. gztar: tar.gz file
  3. bztar: tar.bz2 file
  4. ztar: tar.Z file
  5. tar: tar file
1
python setup.py bdist

可以为bdist指定格式: —formats

  1. gztar: tar.gz file
  2. ztar: tar.Z file
  3. tar: tar file
  4. zip: zip file
  5. rpm RPM Package
  6. pkgtool: Solaris pkgtool
  7. Wininst: Windows上自解压的zip格式的包
  8. msi: Microsoft Installer

bdist_dump
bdist_rpm
bdist_wininst
bdist_msi

获取帮助

1
2
3
4
python setup.py --help
python setup.py --help-commands 所有可以使用的命令
python setup.py COMMAND --help 获取特定命令的帮助
python setup.py COMMAND --help-formats 获取给定命令支持使用的格式

Python安装包

1
python setup.py install

第三方模块默认安装路径默认为site-packages

Python面向对象编程

类用于定义抽象类型。
实例根据类的定义被创建出来。

Python定义类并创建实例

在Python中,类通过class关键词定义。
类体可以包含:申明语句、类成员定义、数据属性、方法

1
2
3
4
5
class Person(object):
pass

xiaoming = Person()
xiaohong = Person()

Python中创建实例属性

每个实例可以拥有各自不同的属性,可以直接给其属性赋值。实例的属性可以像腹痛变量一样进行操作。

Python中初始化实例属性

在定义类时,可以为类添加特殊的init()方法,在创建实例时,init方法会被自动调用。可以在此为每个实例都统一加上属性。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Persion(object):
def __init__(self, name, gender, birth):
self.name = name
self.gender = gender
self.birth = birth

xiaoming = Person('Xiao ming', 'Male', '1992-1-1')

class Persion(object):
def __init__(self, name, gender, birth, **kw):
self.name = name
self.gender = gender
self.birth = birth
for k, v in kw.iteritems():
setattr(self, k, v)

xiaohong = Person('Xiao hong', 'Female', '1992-1-1', jog="student")

init方法的第一个参数必须是self,后面参数可以自由指定,和定义函数没有任何区别。
可以使用setattr将任意关键词参数作为属性赋值给实例。

Python访问限制

Python对属性权限的控制通过函数名来实现,如果一个属性由双下划线开头(__),该属性无法被外部访问。
注意以__开头,以__结尾的属性可被外界访问,__xxx__定义的属性被称为特殊属性。

Python创建类属性

类是模版,实例则是根据类创建的对象。绑定在一个实例上的属性不会影响其他实例,但是,类本身也是一个对象,如果在类上绑定一个属性,则所有实例都可以访问类的属性,并且,所有实例访问的类属性都是同一个!即:实例属性每个实例各自拥有,互相独立,而类属性有且只有一份。
定义类属性直接在class中定义:

1
2
3
4
5
6
7
8
9
class Person(object):
address = "Earth"
def __init__(self, name)
self.name = name

print Person.address

Person.email = '1111@google.com'
Person.address = 'china'

因为类属性是直接绑定在类上的,所有,访问类属性不需要创建实例,就可以直接访问。
对一个实例调用类的属性也是可以访问的,所有实例都可以访问到它所属的类的属性。
由于Python是动态语言,类属性也是可以动态添加和修改的。
因为类属性只有一份,所以,当类的属性改变时,所有实例访问到的类属性都改变了。

Python中类属性和实例属性冲突

当实例属性和类属性重名时,实例属性优先级高,它将屏蔽掉对类属性的访问。
千万不要在实例上修改类属性,它实际上并没有修改类属性,而是给实例绑定了一个实例属性。

方法的可用变量

实例变量:指定变量名称及实例自身进行引用
局部变量:方法内部创建的变量,可直接使用
类变量:通过指定变量名与类名进行引用
全局变量:直接使用

Python中定义实例方法

实例的方法就是在类中定义的函数,第一个参数永远是self,执行调用该方法的实例本身,其他参数和一个普通函数是完全一样的。在实例方法内部可以访问所有实例属性。

1
2
3
4
5
6
7
8
9
class Person(object)
def __init__(self, name)
self.__name = name

def get_name(self)
return self.__name

p = Person('bob')
print p.get_name()

Python中方法也是属性

在class中定义的实例方法其实也是属性,实际上是一个函数对象。
使用types.MethodType()可以把一个函数变成一个方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import types
def fn_get_grade(self):
if self.score >= 80:
return 'A'
if self.score >= 60:
return 'B'
return 'C'

class Person(object):
def __init__(self, name, score):
self.name = name
self.score = score

p1 = Person('Bob', 90)
p1.get_grade = types.MethodType(fn_get_grade, p1, Person)
print p1.get_grade()

p2 = Person('Alice', 65)
print p2.get_grade() # 错误 p2没有get_grade方法

Python中定义类方法

Python类中定义的方法分为类方法和实例方法。
在class中定义的全部都是实例方法,实例方法第一个参数是实例本身。
定义类方法需要使用@classmethod,将方法绑定到Person类上,而非类实例上。类方法的第一个参数传入类本身,因为是在类上调用,而非实例上调用,因此类方法无法获得任何实例变量,只能获得类的引用。

Python类连结至超类的方式

将超类列在类头部的括号内,其从左到右的顺序决定树的顺序,从下至上,从左至右

Python继承

总是从某个类继承,如果没有则需要继承object类。
不要忘记调用super().__init__用来初始化父类属性

1
2
3
class MyClass(object):
def __init__(self)
super(MyClass, self).__init__()

Python中判断类型

函数isinstance()可以判断一个变量的类型,既可以用于Python内置的数据类型,也可以用于自定义类。

Python多态

类具有继承关系,并且子类类型可以向上转型看做父类类型。

Python多重继承

Python允许从多个父类继承,称为多重继承

Python获取对象信息

  1. 用type()函数获取变量的类型,返回一个Type对象。
  2. 用dir()函数获取变量的所有属性。

Python定制类

Python的特殊方法

  1. 特殊方法定义在class中。
  2. 不需要直接调用,某些函数或者操作符会调用对应的特殊方法。

strrepr

如果要把一个类的实例变成str,需要实现特殊方法__str__()
__repr__()方法用于显示给开发人员。

cmp

对int、str等内置数据类型排序时,Python的sorted()按照默认的比较函数cmp排序,如果对自定义类的实例排序,必须提供自定义的特殊方法__cmp__()

len

and

int

@property

slots

call

类、实例和其它对象的内建函数

  1. issubclass() 布尔函数,判断一个类是否由另一个类派生,语法:issubclass(sub, sup)
  2. isinstance() 布尔函数,判断一个对象是否是给定类的实例,语法:isinstance(obj1, class_obj2)
  3. hasattr() 布尔函数,判断一个对象是否拥有指定属性,语法:hasattr(obj, attr) 同类函数getattr()setattr()delattr()
  4. super() 在子类中找到其父类以便于调试其属性,一般仅采用非绑定方式调用祖先类方法,而super()可用于传入实例或类型对象,语法:super(type[,boj])

Python运算符重载

运算符重载在方法中拦截内置操作,当类的实例出现内置操作时,Python自动调用自定义方法,并返回调用结果。运算符重载荣类拦截常规的Python运算,重载使类实例的行为像内置类型,重载通过提供特殊名称的类方法实现。

Python运算符重载

Python运算符重载

Python函数的属性:

  1. __doc__
  2. __name__
  3. __dict__
  4. __code__
  5. __globals__

Python方法的属性:

  1. __doc__
  2. __name__
  3. __class__: 方法所属类
  4. __func__: 实现该方法的函数对象
  5. __self__:调用次方法的实例

Python内置函数:

  1. __doc__
  2. __name__
  3. __self__

Python类:

  1. __doc__
  2. __name__
  3. __bases__
  4. __func__
  5. __module__

Python异常

Python的运行时错误称为异常

  1. 语法错误
  2. 逻辑错误

Python异常是一个对象,表示错误或意外情况,在Python检测到一个错误时,将触发一个异常,Python可以通过异常传导机制传递一个异常,发出一个异常情况的信号。程序员也可以在代码中手动触发异常。
Python异常可以理解为程序出现了错误而在正常控制流程以外采取的行为。

  1. 解释器触发异常,此时当前程序流被打断
  2. 异常处理

错误处理

Python的默认处理:停止程序,打印错误信息。可以使用try语句处理异常并从异常中恢复

事件通知

用于发出有效状态信号

特殊情况处理

无法调整代码去处理的场景

终止行为

try/finally语句可确保执行必需的结束处理机制

非常规流程控制

异常是一种高级跳转机制(goto)

异常通过try语句来检测

任何在try语句块里的代码都会被检测,以检测有无异常发生

try语句两种形式

  1. try-execpt:检测和处理异常,支持多个execpt,支持使用else子句处理没有探测异常的执行的代码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    #定义进行异常监控的一段代码,并提供处理异常的机制
    try:
    try_suite
    execpt Exception[, reason]:
    execpt_suit


    try:
    try_suite
    execpt Exception1[, reason]:
    execpt_suit1
    execpt (Exception2, Exception3, ...)[, reason]: # 一次捕获多个异常使用元组
    execpt_suit2
    execpt: #空execpt用于捕获所有异常
    suit
    else:
    else_suit #没有异常发生时else分句才会执行
    #没有符合的execpt语句时,异常会向上传递到程序之前的try中或者到进程的顶层
  2. try-finally:仅检测异常并做一些必要的处理工作,仅能有一个finally,无论异常是否发生,finally子句都会都会执行,finally中所有代码执行完毕后会向上一层引发异常。

try的复合形式

try-execpt-finally

raise 语句可显式触发异常

raise [SomeException [, args[, traceback]]]

  1. SomeException可选,异常的名字,仅能使用字符串、类或实例
  2. args 可选,以元组的形式传递给异常的参数
  3. traceback 可选,异常触发时新生成的一个用于异常-正常化的跟踪记录,多用于重新引发异常

raise语句的用法大全

Python异常对象

Python异常是内置的经典类Exception的子类的实例,为了向后兼容,Python允许使用字符串或任何经典类实例,Python2.5后,Exception是从BaseException继承的新式类
Python自身引发的所有异常都是Exception的子类的实例,大多的标准异常都是由StandardError派生的,其中三个抽象子类

  1. ArithmeticError 由算数错误而引发的异常基类 OverflowError ZeroDivisonError FlootingPointError
  2. LookupError LookupError 容器在接收到一个无效键或索引时引发的异常的基类 IndexEeror KeyError
  3. EnvironmentError 由于外部原因而导致的异常的基类 IOError OSError WindowsError

Python assert语句

assert语句用于在程序中引入调试代码
assert condition[, expression]
如果condition条件满足,则assert不做任何操作
如果condition条件不满足,则assert使用expression作为参数实例化AssertionError并引发结果实例
如果Python运行使用-O,则assert是一个空操作,编译器不为assert语句生成代码,不使用-O选项,则debug内置变量为True,否则其值为False。

1
2
3
4
# assert condition[, expression] 相当于
if __debug__:
if not condition:
raise AssertionError, <expression>

Python程序的执行

1
2
source code         PVM                     bytecode                PVM
.py ----Complier------> .pyc -----Interpreter----> processor

python源代码第一次执行时被Python虚拟器编译为Python字节码,然后Python虚拟器根据Python字节码执行程序。

Python的实现

Cpython 原始、标准的实现方式
Jythin 用于和Java语言集成的实现
IronPython 用于与.NET框架集合实现

Python性能优化工具

Psyco Python语言的一个扩展模块,即时对程序代码进行算法优化,可以一定程度提高程序的执行速度,尤其是程序中有大量循环操作时,目前该工具研发工作已经停止,由pypy所替代。
PyPy PyPy是用Python实现的Python解释器,Python语言的动态编译器,是Psyco的后继项目。可以运行在Linux32和64位、MocOS和Windows的32位平台上。
Shed Skin Python编译器,能将Pythona代码转化为优化的C++代码。

Python程序文件

Python程序可分解为模块、语句、表达式和对象

  1. 程序由模块组成
  2. 模块包含语句
  3. 语句包含表达式
  4. 表达式建立并处理对象
    1. 表达式是”某事”,而语句是”做某事(即指令)”。
    2. 语句的特性:改变令事物。

面向过程:以指令为中心,由指令处理数据
面向对象:以数据为中心,所有的代码都围绕数据展开

Python要素 基本数据类型

Python要素 对象引用

  1. Python将所有数据都存为内存对象,Python中变量其实是指向内存对象的引用。
  2. 动态类型:在任何时刻,只要需要,某个对象引用都可以重新引用一个不同的对象。
  3. 内建函数type()用于返回给定数据项的数据内型。
  4. “=”用于将变量名与内存中的某个对象绑定:如果对象事先存在,就直接进行绑定;否则,则在”=”创建引用的对象。
  5. 注意,变量名没有类型,对象才有。
  6. 列表和元素并不存储数据,而是存放对象引用

Python要素 组合数据类型

Python要素 逻辑操作符

Python提供4组逻辑运算

  1. 身份操作符 is,判断左端对象引用是否相同于右端对象,也可以与None进行。
  2. 比较操作符 <, >, <=, >=, !=, ==
  3. 成员操作符 in 或 not in:测试成员关系
  4. 逻辑运算符:and、or、not

Python要素 控制流语句

Python要素 算数运算符

Python提供了完整的算数操作符。
Python的int类型是不可变的,因此给一个int变成加减其实是重新创建一个新的变量来存储结果后将变量名执行重新绑定。
Python int算数操作

Python要素 输入/输出

命令行输出 print()函数 python3 print语句 python2
命令行输入 input() raw_input()
Python解释器提供3种标准文件对象,标准输入sys.stdio 标准输出sys.stdout 标准错误sys.stderr, 存在与sys模块中。

Python要素 函数

callable()函数可以检测函数是否可调用。
Python有很多内置函数 __builtins__
Python有很多标准库,可以导入后直接使用。

Python 语句和语法

注释 #
续行 \ ‘’’
代码组 缩进相同的一组语句可构成代码块 首行以关键字开始,以冒号结束,Python使用缩进来分隔代码组,同一代码组的代码行必须严格左对齐,否则会造成语法错误。
同一行多个语句,以;为分隔符
模块 每个Python脚本文件都是一个模块

Python 文件结构

  1. 起始行 #/usr/bin/env python
  2. 模块文档(文档字符串) __doc__
  3. 模块导入
  4. (模块全局)变量定义
  5. 类定义(若有)
  6. 函数定义(若有)
  7. 主程序

每个模块都有__name__内建变量,此变量根据调用该模块的方式而变化。__name__指示模块该如何加载,如果模块是被导入,__name__的值是模块名字 如果模块是直接执行__name__的值是__main__

Python两个对象比较

  1. 值比较:对象中的数据是否相同
  2. 身份比较:两个变量引用的是否同一个对象 也就是内存地址比较
  3. 类型比较:两个对象的类型是否相同

Python类型转换

个人理解Python中类型转换,都是根据原有对象新建对象
str() repr()或format():字符串
int():整数
float():浮点数
list():列表
tuple():元组
set():集合
dict():字典,传入参数必须是(key, value)的元组序列
chr():字符(ASCII码),传入参数为整数
ord():整数,传入参数为字符
hex():16进制整数
bin()
cot()

Python数字类型

Python 5种数字类型:布尔型(True 1 False 0)、整数、长整数、浮点数、复数,所有数字类型均不可变。
数字操作: 加+-*/ 截断除法// 乘方 ** 取模%
位操作:左移 << 右移 >> 按位与& 按位或| 按位异或^ 按位求反~

Python序列类型

Python内置序列类型list tuple str str是字符序列 list和tuple是任何Python对象序列 str和tuple属于不可变序列 所有序列都支持迭代
所有序列类型支持索引、切片
min()取序列中的最小值
max()取序列中的最大值
sum()对序列求和
len()求序列元素个数
all()检查序列中所有元素为True

Python列表

支持在原处修改:修改指定的索引元素、修改指定分片、删除语句、内置方法
合并两个列表,返回一个新的列表,不会修改原列表
in:成员关系判断字符,用法 obj in container
not in: obj not in container
列表解析:[]
列表复制:浅拷贝 深拷贝(copy.deepcopy())

Python元组

任意对象的有序集合,通过索引访问其中内容,不可变对象,长度固定
in
not in

序列类型的操作 列表类型的操作

Python集合

只能使用工厂函数set()和frozenset()创建
不支持:索引、切片、元素获取
集合类型的操作

Python引用计数

sys模块 sys.getrefcount()获得对象的引用计数
Python对象引用计数为0,对象被释放,归还内存

Python真假

  1. 所有非0数字和非空对象都为真
  2. 数字0、空对象和特殊对象None均为假

Python解释器环境与选项

python [option] [-c cmd | filename | -] [ args ]
Python解释器启动选项
Python解释器环境变量

Python文件操作

Python内置函数open()用于打开文件和创建文件对象。

1
open(name [,mode[,bufsize]])

open方法可以接受三个参数:文件名、模式、缓冲区参数

  1. open函数返回一个文件对象
  2. mode指定文件打开模式 r只读 w写入(如果没有文件会自动创建一个) a附加 r+默认读模式打开支持写操作 w+默认写模式打开支持读操作 a+默认附加模式打开支持读操作 在r、w、a、r+、w+、a+后面中附加b,表示以二进制方式打开
  3. bufsize定义输出缓存 0表示无输出缓存 1表示使用缓存 负数表示使用系统默认配置 正数表示使用近似指定大小的缓冲。

file.next() 返回文件中下一行内容 不会移动文件游标
file.close() 关闭当前文件
file.fileno() 返回文件描述符
file.readline() 读取文件中一行
file.readlines() 以列表形式每行为一个元素,返回所有文件内容
file.tell() 返回当前文件游标的位置(第n个字节处)
file.read(size) 返回size个字节的数据,返回字符串
file.seek(offset [, whencel]) 移动文件游标到指定位置 offset偏移量 whencel 偏移起点 0文件头 1当前位置 2文件尾部 默认为0
file.write(str) 将str写入文件中
file.writeline(list) 将字符串列表list写入文件中
file.flush() 将数据从缓存区刷新到磁盘中
file.isatty() 判断该文件是否为终端设置文件 如果是返回True 否则返回False
file.truncate(size) 将文件截取保留size大小的文件,其余的删除

file.closed 返回文件是否已经关闭 返回True表示已关闭 返回False表示未关闭
file.encoding 返回文件编码格式
file.mode 返回文件打开模式
file.name 当前打开文件名称
file.softspace

Python OS模块

目录相关
os.mkdir(path) 创建目录path
os.mkdirs(path) 创建目录path如果父目录不存在先创建父目录
os.rmdir(path) 删除目录path
os.rmdirs(path) 删除多级目录
os.getcwd() 返回当前目录
os.chdir(path) 改变当前目录为path
os.fchdir(file) 通过文件描述符改变当前目录
os.chroot() 设定当前进程的根目录
os.listdir(path) 列出指定目录下的所有文件名

文件相关
os.stat(path) 获取path的状态信息
os.remove(file) 删除文件
os.rename(file) 文件重命名
os.symlink(src, dst) 创建链接
os.utime(path) 更新时间
os.walk()

权限相关
os.access(path, mode) 检验权限是否存在
os.chmod(path, mode) 修改权限为mode
os.chown(path, pid, gid) 改变文件的属主和属组权限)
os.umask() 设置默认权限模式

文件描述符
os.open()
os.close()
os.read()
os.write()

os.path 文件路径相关
os.path.basename() 文件名
os.path.dirname() 目录名
os.path.join() 整合路径
os.path.split() 返回dirname() basename()元组
os.path.splitext() 返回(filename, extension)元组

os.path.getatime()
os.path.getctime()
os.path.getmtime()
os.path.getsize() 返回文件大小

os.path.exists() 判断指定文件是否存在
os.path.isabs() 判断给定路径是否为绝对路径
os.path.isdir() 判断是否为目录
os.path.isfile() 判断是否为文件
os.path.islink() 判断是否为链接
os.path.ismount() 判断是否为挂载点
os.path.samefile() 判断两个路径是否指向同一文件

对象流式化、持久化
pickle

Python 文件对象可迭代

1
2
3
4
5
In [14]: f = open('/etc/passwd' , 'r')

In [15]: for line in f:
....: print line
....:

Python正则表达式

基础知识

正则表达式,使用单个字符串来描述、匹配一系列符合某个语法规则的字符串。
常用正则表达式的表达式符号和特殊字符

  1. literal 匹配字符串的值 例如: foo
  2. re1|re2 匹配正则表达式re1或re2 例如: foo|bar
  3. . 匹配任何单个字符(换行符除外) 例如: b.b
  4. ^ 匹配字符串的开始 例如: ^Dear
  5. $ 匹配字符串的结尾
  6. * 匹配前面出现的正则表达式零次或多次 例如: [A-Za-z0-9]*
  7. + 匹配前面出现的正则表达式一次或多次 例如: [a-z]+.com
  8. ? 匹配前面出现的正则表达式零次或一次 例如: goo?
  9. {N} 匹配前面出现的正则表达式N次 例如: [0-9]{3}
  10. {M,N} 匹配前面出现的正则表达式M次到N次 例如: [0-9]{5,9}
  11. [...] 匹配字符组里出现的任意一个字符 例如: [aeiou]
  12. [..x-y..] 匹配从字符x到字符y的任意一个字符 例如: [0-9], [A-Za-z]
  13. [^...] 不匹配此字符集中出现的任何一个字符,包括某一范围的字符(如果在次字符集中出现)例如: [^aeiou], [^A-Za-z0-9_]
  14. (*|+|?|{})? 用于上面出现的任何“非贪婪”版本重复匹配次数符号(*,+,?,{}) 例如: .*?[a-z]
  15. (...) 匹配封闭括号中正则表达式(RZ), 并保存为子组 例如: ([0-9]{3})?,f(oo|u)bar
  16. \d 匹配任何数字,和[0-9]一样(\D\d的反义:任何非数字符) 例如: data\d+.txt
  17. \w 匹配任何数字字母字符,和[A-Za-z0-9]相同(\W\w的反义) 例如:[A-Za-z\_]w+
  18. \s 匹配任何空白符,和[\n\t\r\v\f]相同,(\S\s的反义) 例如: of\sthe
  19. \b 匹配单词边界(\B\b的反义) 例如: \bThe\b
  20. \c 逐一匹配特殊字符c(即,取消它的特殊含义,按字面匹配) 例如: \., \\, \*
  21. \A(\Z)匹配字符串的起始(结束) 例如: \ADear

Python正则表达式模块

re模块
re.match() 尝试用正则表达式模式从字符串的开头匹配,如果匹配成功,则返回一个匹配对象,否则返回None
re.search() 在字符串中查找正则表达式模式第一次出现,如果匹配成功,则返回一个匹配对象,否则返回None
re.findall() 在字符串中查找正则表达式默认的所有(非重复)出现;返回一个匹配对象的列表
re.split() 根据正则表达式中的分隔符将字符分割为一个列表,返回成功匹配的列表,可以设定次数(默认是分割所有匹配的地方)
re.sub() 把字符串中所有匹配正则表达式的地方替换为字符串,如果没有次数限制,则对所有匹配的地方进行替换,并返回替换后整个串
re.subn() 和re.sub()功能相同,不过其返回值为元组,包含其替换后的串和替换次数
re.compile()

贪婪匹配和非贪婪匹配

当正则表达式中包含能接受重复的限定符时,匹配尽可能多的字符,即贪婪匹配。贪婪匹配:a.*b,将会匹配最长的以a开始以b结束的字符串。如果以它来搜索aabab的化,会匹配整个字符串aabab。
非贪婪匹配,在正则表达式后面加个?。 .*?意味着在能使匹配成功的前提下使用最少的重复。a.*b匹配最短的以a开始以b结束的字符,应用于aabab的话,会匹配aab和ab。

Python使用过程中碰到问题

python josn dumps中文乱码问题

1
2
3
4
5
6
7
8
9
In [1]: strMsg = {"测试":"值"}

In [2]: import json

In [3]: print json.dumps(strMsg)
{"\u6d4b\u8bd5": "\u503c"}

In [4]: print json.dumps(strMsg, ensure_ascii=False)
{"测试": "值"}