基础语法
- 使用缩进来组织代码块
- 大小写敏感
- 基本数据类型:空值None、布尔值、整数、浮点数、字符串
- 程序运行过程中,变量存储在内存中
- 变量本身类型不固定 - 动态语言
- 常量通常用全大写表示
- 1个中文字符经过UTF-8编码后通常会占用3个字节,而1个英文字符只占用1个字节
- encode()编码,decode()解码
- 列表list,有序集合,[]
- 元组tuple,类似list,(),一旦定义内容不可变
- 字典dict,无序键值对,{}
- Set,无序无重复元素的集合,只存储key,以set()方法构建,参数为一个list
- 函数返回多个值其实是返回一个tuple(省略了括号)
- 函数参数类型:必选参数、默认参数、可变参数、*关键字参数、命名关键字参数
- 关键字参数在函数内部自动组装成为一个dict
- 命名关键字参数是为了限制调用者可以传入的参数名,同时可以提供默认值
- 参数组合顺序:必选参数、默认参数、可变参数、命名关键字参数和关键字参数
- *args是可变参数,接收一个tuple
- **kw是关键字参数,接收一个dict
- 对于任意函数,都可以通过func(*args, **kw)的形式调用
- 如果函数中包含yield关键字,那么这个函数就不再是一个普通函数,而是一个generator
- 可以直接作用于for循环的对象统称为迭代对象Iterable,包括str list tuple dict set generator
- 可以被next()函数调用并不断返回下一个值的对象称为迭代器Iterator
- 可以使用iter()函数把Iterable变成Iterator
- Iterator对象表示一个数据流,一个惰性计算的序列,只有在需要时才返回下一个值
函数式编程
- 函数是面向过程的程序设计的基本单元
- 函数本身可以赋值给变量,即变量可以指向函数,指向函数的变量其实就是函数名
- 把函数作为参数传入,这样的函数称为高阶函数,这种高度抽象的编程范式称为函数式编程
- 典型高阶函数:map() reduce() filter() sorted()
- map()把参数函数作用在参数list的每一个元素上,并返回一个新的Iterator
- reduce()把参数函数作用于参数list,并把返回结果参与到下一个元素的运算
- filter()过滤序列
- sorted()将key指定的函数作用于list的每一个元素上,并根据函数返回的结果进行排序
- lambda匿名函数,只能有一个表达式,返回值就是该表达式的结果
- 匿名函数可以赋值给变量,也可以作为函数返回值
- 使用list(Iterator)获取惰性序列的所有值
- 高阶函数除了可以将函数作为参数外,还可以将函数作为结果值返回
- 闭包 - 在外部函数中定义内部函数,内部函数可以引用外部函数的参数和局部变量,
- 当外部函数将内部函数作为结果值返回时,相关参数和变量都保存在内部函数中
- 返回函数不要引用任何循环变量,或者后续会发生变化的变量
- 函数也是一个对象,而且可以被赋值给变量,通过变量也能调用该函数
- 在函数运行期间动态增加功能的方式,称之为装饰器Decorator
- 装饰器的本质是返回函数的高阶函数
- 使用@functools.wraps()把原始函数的name属性复制到装饰器中的函数
- 偏函数functools.partial()的作用就是把一个函数的某些参数固定住,即设置默认值,然后返回一个新的函数
面向对象编程
- 在类中定义的函数,第一个参数永远是实例变量self,调用时不用传递该参数
- 在类属性前加两个下划线,则变成了一个私有变量,外部不可直接访问
- 特殊变量xxx是可以直接访问的
- 多态 - 子类中的方法覆盖父类中的同名方法
- 常用的对象分析方法:dir() hasattr() getattr() setattr()
- 实例属性将屏蔽掉同名的类属性
- 定义一个类,创建一个实例后,可以给该实例绑定任意属性和方法(仅属于当前实例)
- 使用slots限制类实例可以添加的属性和方法,对继承的子类不起作用
- 内置的@property装饰器负责把一个方法变成属性调用,简化对属性的getter/setter操作
- Python支持多重继承,一个子类可以同时获得多个父类的所有功能
- 在设计类的继承关系时,通常主线都是单一继承下来的,然后”混入”额外的功能,称之为MixIn
- 常用的定制类方法:str repr iter next getitem getattr call
- Enum可以把一组相关常量定义在一个枚举类中,且该类不可变,成员可以直接比较
- 动态语言,函数和类的定义,不是编译时定义的,而是运行时动态创建的
- type()既可以返回一个对象的类型,又可以创建出新的类型
- 元类metaclass,先定义metaclass,就可以创建类,然后创建实例,即可以把类看作是metaclass创建的”实例”
- 元类的常用使用场景:ORM框架
错误和异常处理
- 错误和异常是class,捕获一个错误就是捕获到该class的一个实例
- 捕获异常try…except(else)…finally,抛出异常raise
- 所有错误和异常都继承自BaseException
- 程序调试:打印print(),断言assert(),日志logging,单步执行pdb,断点pdb.set_trace()
- 日志级别logging.basicConfig(level=logging.INFO) debug info warning error
- TDD Test-Driven Development 测试驱动开发
- 内置单元测试模块unittest,方法setUp、tearDown
- 文档测试doctest,不但可以用来测试,还可以直接作为示例代码 ”’ this is doctest ”’
网络编程
- 网络通信本质是两台计算机上的两个进程之间的通信
- TCP协议是建立在IP协议之上的,更高级的协议(HTTP协议、SMTP协议等)是建立在TCP协议之上的
- 小于1024的是Internet标准服务的端口,大于1024的可以任意使用
- 基于TCP协议进行Socket编程,客户端要主动连接服务器的IP和指定端口
- 对于服务器,要首先监听指定端口,然后对每一个新的连接,创建一个线程或进程来处理,通常服务器会无限运行下去
- 用户数据报协议UDP(User Datagram Protocol),是面向无连接的协议
- 与TCP相比,UDP不需要连接,速度更快,但数据传输的可靠性较差,不能保证数据一定发送成功
- 服务器绑定TCP端口和UDP端口互不冲突,也就是说,TCP的9999端口与UDP的9999端口可以各自绑定
电子邮件
- 电子邮件基本路径:发件人 -> MUA -> MTA -> MTA -> 若干个MTA -> MDA <- MUA <- 收件人
- MUA: Mail User Agent 邮件用户代理,如Foxmail
- MTA: Mail Transfer Agent 邮件传输代理,如网易163
- MDA: Mail Delivery Agent 邮件投递代理
- MUA和MTA使用的协议SMTP: Simple Mail Transfer Protocol
- MUA和MDA使用的协议POP: Post Office Protocol和IMAP: Internet Message Access Protocol
- Python内置对SMTP的支持,模块email负责构造邮件,smtplib负责发送邮件,可以发送纯文本、HTML邮件及带附件的邮件
- poplib用来接收邮件,email用来解析邮件
数据库操作
- SQLite是一种嵌入式数据库,它的数据库就是一个文件
- SQLite由C语言写成,体积很小,所以经常被集成到各种应用程序中,甚至移动APP中
- Python内置了SQLite及相关驱动
- 操作数据库的基本步骤:创建连接 -> 获取游标 -> 执行SQL -> 关闭游标 -> 提交事务(非查询操作) -> 关闭连接
- 使用游标Cursor对象执行insert update delete语句时,执行结果由rowcount返回影响的行数
- 使用游标Cursor对象执行select语句时,通过fetchall()可以获取结果集
- 结果集是一个list,每个元素都是一个tuple,对应一行记录
- Python的DB-API定义对不同的数据库是通用的
- 执行INSERT等操作后要调用commit()提交事务
- MySQL的SQL占位符是%s
- ORM(Object-Relational Mapping)对象关系映射
- ORM就是把数据库表的行与相应的对象建立关联,把对表的操作转换为对对象的操作
- 常用ORM框架:SQLAlchemy
Web开发
- Web开发阶段:静态HTML -> CGI -> PHP/ASP/JSP -> MVC -> MVVM
- CGI: Common Gateway Interface, 由C/C++编写
- HTTP 1.1版本允许多个HTTP请求复用一个TCP连接,以加快传输速度
- 一个HTTP请求只处理一个资源
- HTTP响应的数据格式由Content-Type决定的
- Content-Encoding: gzip是指以gzip方式对Body数据进行压缩
- Apache Nginx Lighttpd是静态服务器
- Python是解释性的脚本语言,适合Web开发,有上百种Web开发框架
- WSGI: Web Service Gateway Interface
- Python内置了一个WSGI服务器,这个模块叫wsgiref,它是用纯Python编写的WSGI服务器的参考实现
- Flask通过Python的装饰器在内部自动地把URL和函数给关联起来,默认支持模板jinja2
- 常用Web开发框架:Flask Django web.py Bottle Tornado
- 常用模板:jinja2 Mako Cheetah Django
IO编程
- 流Stream, Input Stream是数据从磁盘、网络流入内存,Output Stream是从内存流出
- 同步IO和异步IO的主要区别在于是否等待IO执行的结果
- 异步IO的执行效率更高,但编程模型也更复杂
- 读写文件是最常见的IO操作,该功能是调用操作系统提供的接口实现的
- 操作系统在同一时间能打开的文件数量是有限的
- 使用with语句操作文件IO,可以确保文件被关闭
- 打开文件open(‘file’, ‘r/w’, encoding=’utf-8’, errors=’ignore’) -> 读read()/写write() -> 关闭文件close()
- StringIO和BytesIO是在内存中操作str和bytes的方法,使得和读写文件具有一致的接口,getvalue()
- os模块封装了操作系统的目录和文件操作,要注意这些函数有的在os模块中,有的在os.path和shutil模块中
- 把变量从内存中变成可存储或传输的过程称作序列化pickling, 反序列化unpickling
- 通过pickle json模块来实现序列化,dumps() loads()
进程和线程
- 单核CPU以时间片轮转的方式来执行多任务,真正的并行执行多任务需要在多核CPU上实现
- 一个进程Process至少有一个线程Thread,线程是最小的执行单元
- 多任务实现:多进程模式 多线程模式 多进程+多线程模式
- 调度进程和线程,完全由操作系统决定,程序自己不能决定什么时候执行,执行多长时间
- 在Unix/Linux下,可以使用os.fork()调用实现多进程,跨平台可以使用multiprocessing模块
- 使用进程池的方式批量创建子进程
- 进程间通信通过Queue Pipes等实现
- 任何进程默认都会启动一个线程,称为主线程MainThread,主线程又可以启动新的线程
- 在多进程中,同一个变量在每个进程中有一份拷贝,互不影响;在多线程中,变量在线程间共享
- 使用线程锁threading.Lock()来对线程进行隔离,避免冲突
- Python进程有各自独立的GIL锁,互不影响,因此可以使用多进程来实现多核任务,但无法使用多线程来实现
- ThreadLocal变量虽然是全局变量,但每个线程都只能读写自己线程的独立副本,互不干扰
- 采用多任务需要考虑的因素:任务数量(线程切换)和任务类型(计算密集型 vs IO密集型)
异步IO
- 进程更稳定,而且可以分布到多台机器上,而线程最多只能分布在同一台机器的多个CPU上
- 使用QueueManager模块实现分布式进程
- Nginx是支持异步IO的Web服务器,使用单进程单线程模型来执行多任务,称为事件驱动模型
- 在Python中,单线程的异步编程模型称为协程Coroutine
- 使用asyncio模块来实现异步IO
- asyncio实现了TCP UDP SSL等协议,aiohttp是基于asyncio实现的HTTP框架
其他
- 正则模块re.match()返回match对象或None
- Python支持多种图形界面的第三方库:Tk wxWidgets Qt GTK,内置支持Tk的Tkinter