python教程

基础

环境

  • 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.

你可能感兴趣的:(python教程)