基础
环境
REPL
ipython
emacs
实践: hello, world
类型
字符变量
数字变量
布尔变量
序列容器
非序列容器
第一类函数对象(first class function)
结构
选择结构
循环结构
迭代结构
块结构
实践: Guess the number/with feedback
函数
普通函数
匿名函数
变长参数
参数默认值
生成器
实践: fibonacci/memorized
小技巧
列表推导式
闭包
装饰器
map/reduce
作用域规则(scoping)
LGB
LEGB
unbound
实践: 24 game
面对对象
类
成员变量
成员函数
可见性
继承
property
多继承
plugin
实践:
balanced tree/two dimension
balanced tree/three dimension
异常
执行转移
系统异常和程序异常
实践: 异常重定向
模块
路径和导入规则
实践: dynamic plugin modules
闭包和对象类的联系
class Out(object):
def __init__(self, a, b, c):
self.a, self.b, self.c = a, b, c
def __call__(self):
use self.a, self.b, self.c
return xxx
装饰器注册
class Reg(object):
def __init__(self):
d = {}
def register(self, path):
def inner(f):
self.d[path] = f
return f
return inner
reg = Reg()
@reg.register('/abc/')
def action1():
pass
反模式
函数默认值
函数的默认值,在同一个函数内是同一个。不要用可变值作为默认值。
def sumobj(l=None):
if l is None: l = []
return reduce(lambda x, y: x+y, l)
局部变量定义
在内层中后定义的对象会导致先使用的对象出错,尤其在全局有同名变量时,这容易产生混淆。
a = 1
def func():
print a
a = 2
更具有迷惑性的例子:
a = 1
def func():
if True: print a
else: a = 2
battery inside
内置模块
os
sys
re
path
datetime
logging
math
random
shutil
hashlib
getopt
collections
ConfigParser
实践: getopt
文件系统
读写
管理
对象序列化
json
pickle
marshal
不同格式读写
csv
zipfile
tarfile
实践: find duplicate files
第三方模块
requests
beautifulsoap
高级特性
测试
unittest
示例:
hashlib
调试
pdb
块
使用
定义
流
每次取得一个元素
不可跳过下一个元素取得后续元素
不可回朔前一个元素
过滤和映射
列表推导 [map(i) for i in list if filter(i)]
循环
rslt = []
for i in list:
if filter(i): continue
i = map(i)
rslt.append(i)
函数式
def proc(i):
do i
def isi(i):
test i
map(proc, filter(isi, list))
注意itertools的imap和ifilter才是生成器模式,2.7中的map和filter都是直接把结果list生成出来的。
dict过滤
dict([(mapk(k, v), mapv(k, v)) for k, v in dict.iteritems() if filter(k, v)])
dict推导式(python3后有效) {k: v for k, v in dict.iteritems()}
列表推导和循环隐含假定不可并发,函数式隐含假定可并发。
过滤装饰器
结合生成器流和过滤的手法。
def filterxxx(list):
for i in list:
if filter(i): continue
i = map(i)
yield i
for i in filterxxx(source):
do i
优点是很容易写出多层过滤正交。
实践: find duplicate files/insertable functions
网络
底层协议
tcp协议栈
服务器端
客户端
udp协议栈
实践: ping-echo server(tcp and udp mode)
应用层协议
urllib
smtplib
代码风格
过程式风格
一行语句完成一项简单工作
自行显式管理中间变量
偏好迭代而非递归
基本控制结构为分支和循环
面对对象风格
复杂的对象和继承结构
对象拥有众多方法
对外暴露一致性抽象接口
要点
不要在基类中声明一遍未实现
可以放弃显式基类,改为约定基类(duck typing)
多接口可以用maxin模式实现
少用super
函数式风格
大量使用高阶函数和第一类函数对象
在小幅使用闭包替代微型类
一行流,代码经常写成lisp缩进风格
经常使用“无副作用函数”
偏好递归而非迭代
基本控制结构为函数构造形态
要点
不要过度迷信函数对象,尤其是在python没有尾递归优化,函数调用开销又很高的情况下。
注意什么时候用闭包,什么时候用类。
lisp风格的一行流不利于调试,python没有调用树中间显示,因此在这一行上报出的错误可能是在任何一个调用中,需要自行判断
lambda可以用于lazy evaluation,很有用
结合多种风格
在面对对象风格的具体函数实现中,可能出现局部的过程风格和函数风格。
对象可能大量产生一类函数对象,用于高阶函数中。
完成目标的风格是最好的风格
哲学
duck typing
没有基类,却行为一致,就可以互换使用
不要将静态语言思路用于动态语言,尤其是多重继承和父类的空函数
正确的传递和处理参数是程序员的责任,不是IDE的
POLA
the principle of least astonishment
函数返回值是否有多种可能,需要根据情况来判断?
函数返回值确定,但是值的类型是否多变?
错误处理
函数不可能又返回值又返回错误,使用异常处理错误。
尽早出错。不要做输入检测,不要写保护性代码,不要容错,不要处理异常。
不要捕获额外的错误,尤其禁止捕获Exception
尽量使用python现有的异常,例如ValueError。除非有必要做出区分。
Errors should never pass silently, Unless explicitly silenced.