python 笔记
独立环境
graph TB pyenv-->wrappervirtualenv_lazy wrappervirtualenv_lazy-->mkvirtualenv mkvirtualenv-->workon
I/O multiplexing
graph TB DefaultSelector--生成事件注册-->register fileobj--参数-->register events--参数-->register data--参数-->register register--instance-->SelectorKey SelectorKey--event is ready-->select select --> event_list("[(key, events),(SelectorKey instance, bitmask of events ready ),...]") event_list-->SelectorKey event_list-->mask SelectorKey-->fileobj SelectorKey-->fd SelectorKey-->events SelectorKey-->data
设计模型
1. 装饰器(decorator)模式
(俄罗斯套娃封装)
1 |
|
- 创建一个装饰函数,内部定义一个wrapper新函数执行一些操作,将被装饰函数作为参数传入装饰函数,返回新函数
- 行为类似多重继承.
- 当在装饰器与继承之间选择时,只需要根据一些条件对对象进行动态修改时使用装饰器.
- 日志装饰器,传递一些参数动态记录日志
- 作用:
- 增强核心对象的能力
- 让核心对象支持多种可选行为
- 编写判断执行不同的装饰器
2. 观察者模式
状态监测,事件处理
1 | 核心对象->update()->观察者们->各自处理自已的任务 |
3. 策略模式
每个策略类都包含同名方法,接收相同参数.
1 | 核心对象->策略1 |
4.状态模式
状态类的目的是实现状态转换,需要一个上下文类提供转换接口和指针指向状态类,状态类对前面的调用者是隐藏的.
1 | Context -> state -> [state1, state2, state3] -> Parser |
策略模式用于运行时选择一种算法,如一张图片根据不同的情况处理成不同的状态
状态模式用于允许在不同状态之间进行动态切换,如解析XML文件,context上下文切换
5.单件模式
只有一个实例的对象类.
模块级实例变量能够模仿单件实例
6.模板模式
7.适配模式(adapter)
接口适配转换
8.外观模式(facade)
为复杂的组件提供典型用途的简单接口,如requests为urllib,编写发送邮件的类为smtplib,samplib等
9.享元模式
专为节省内存而设计的,如果有成百上千的相同对象,将相同特性整合进一个享元可极大减少内存消耗.
10.命令模式
11.抽象工厂模式
12.组合模式
简单的组件构成复杂的树状结构
迭代器iterator&递归器
- 迭代器
- 字符串(有时需要将字符串视为原子的.否则有时有可能导致无穷递归.)
- 每次只取一个对象,不会对内存造成巨大开销.
- 递归器
表达式 & 语句
- 表达式有返回值
- yield是表达式,所以调用生成器需要next()来执行表达式
- send是传递值给yield表达式
python 运算符
Python逻辑运算符
Python语言支持逻辑运算符,以下假设变量 a 为 10, b为 20:
运算符 | 逻辑表达式 | 描述 | 实例 |
---|---|---|---|
and | x and y | 布尔”与” - 如果 x 为 False,x and y 返回 False,否则它返回 y 的计算值。 | (a and b) 返回 20。 |
or | x or y | 布尔”或” - 如果 x 是非 0,它返回 x 的值,否则它返回 y 的计算值。 | (a or b) 返回 10。 |
not | not x | 布尔”非” - 如果 x 为 True,返回 False 。如果 x 为 False,它返回 True。 | not(a and b) 返回 False |
数学运算
1 | + plus |
1 | print "If I add %d, %r, and %d I get %d." % (my_age, my_height, my_weight, my_age + my_height + my_weight) |
标识符 %s, %r, %d
byte & string
Unicode
字符串和二进制数据流
1 | # bytes object |
编码就是把一个字符用一个二进制来表示。
字符串类str里有一个encode()方法,它是从字符串向比特流的编码过程。而bytes类型恰好有个decode()方法,它是从比特流向字符串解码的过程。
ASCII码,一种8位即1个字节的编码规范,它可以涵盖整个英语系的编码需要。
python 中编码print后会以ascii编码方式显示,所以中文会显示16进制,英文会直接显示ascii后的原文.
世界标准:
ASCII(en:1byte,8bits) =>
unicode(en:2bytes,16bits; cn:3bytes,24bits) =>
utf-8(en:1byte,8bits; cn:3bytes,24bits)
中国标准
GBK 2bytes, 16bits
输入
raw_input()
Parameters
argument 命令行参数
Parameters
文件读写
close – Closes the file. Like File->Save.. in your editor.
read – Reads the contents of the file. You can assign the result to a variable.
readline – Reads just one line of a text file.
truncate – Empties the file. Watch out if you care about the file.
write(‘stuff’) – Writes “stuff” to the file.
函数
匿名函数
lambda x: x * 8
回调函数
作为参数传入中间函数的函数
回调实际上有两种:阻塞式回调和延迟式回调。两者的区别在于:阻塞式回调里,回调函数的调用一定发生在起始函数返回之前;而延迟式回调里,回调函数的调用有可能是在起始函数返回之后。
中间函数
需要传入回调函数的函数
起始函数
调用中间函数的函数
装饰函数
代码风格
1
2
3
4
5
6
7
8
9
10
11
12def logging_tool(func):
def wrapper(*arg, **kwargs):
logging.info('%s is running...' % func.__name__)
# 把today当作参数传递进来,执行func()就相当于执行today()
func()
return wrapper
def today():
print('2018-05-25')
today()
多进程,多线程
What is a process? A process is just an instance of an executing program.
sbla(socket, bind, listen, accept)
process -> UNIX fork()
进程>线程>协程
Python对协程的支持是通过generator实现的。
子程序顺序栈式调用,不可乱序
协程(Coroutine)中断式调用,可乱序
子程序,或者称为函数,在所有语言中都是层级调用(栈式调用),比如A调用B,B在执行过程中又调用了C,C执行完毕返回,B执行完毕返回,最后是A执行完毕。
子程序调用总是一个入口,一次返回,调用顺序是明确的。而协程的调用和子程序不同。
Python中的协程大概经历了如下三个阶段:
- 最初的生成器变形yield/send
- 引入@asyncio.coroutine和yield from
- 在最近的Python3.5版本中引入async/await关键字
同步的异步实现
借助 Python 的 generator 功能,Twisted 和 Tornado 纷纷提供了这样的功能。
生成器(generator)(协程)(yield,需要多次调用:执行先中断,返回变量,再执行.)
函数是顺序执行,生成器也是顺序计算的.
协程看上去也是子程序,但执行过程中,在子程序内部可中断,然后转而执行别的子程序,在适当的时候再返回来接着执行。
注意,在一个子程序中中断,去执行其他子程序,不是函数调用,有点类似CPU的中断。
列表推导式 -> []
- 直接打印
生成器推导式 -> ()
- next(generator)激活,最后一个返回StopIteration error
- generator保存的是算法,调用才开始计算
- 可迭代对象
- 生成器并没有将所有值放入内存中,而是实时地生成这些值,并且不会保存上一次迭代生成的值,因而,在迭代一个比较大的数据的时候,使用迭代器更好
- yield 的作用就是返回迭代器
- python直到遇到关键字yield之后,中断代码执行,返回yield变量值
- send 函数就是给yield语句赋值
- 先调用,返回原值(send并不会改变yield的返回值)
- 发送send,修改变量,并返回next值
- 因为当send方法的参数为None时,它与next方法完全等价(不规范,慎用)
- close可以关闭生成器
生成器使用场景
- 项目中如何使用yield,使用的思路就是,中断代码执行,在yield之前打开一个资源,然后在yield之后关闭这个资源,这样可以很好地保证每次只有一个资源被打开,同时执行完成之后资源会被关闭
- 第二个思路,就是节约内存,不要一下子加载所有的资源
- IO密集型
条件判断
if 语句的判断条件可以用>(大于)、<(小于)、==(等于)、>=(大于等于)、<=(小于等于)来表示其关系。
True & False
针对Python中的True和False的定义,在不同版本的Python中是这样定义的:
- Python 2:None, 0, 和空字符串都被算作 False,其他的均为 True
- Python 3:None,0,空字符串,空列表,空字典都算是False,所有其他值都是True
面向对象
propterty() and @property:对属性做限制/检查操作
类属性
实例属性
1 | class Person(): |
编写代码首要考虑它的可读性(DRY不要让自己重复)
- 继承(超类里也可定义子类才有的方法,使得自己成为通用类)
- 组合(大部分继承关系都可以建模替代为组合关系,反之大部分组合都不能建模为继承)
- 关联
如果只对数据操作->使用python数据结构
如果只关注行为不存储数据->使用函数
如果同时包含数据和行为 ->使用对象->代码更易读而不关心长短,对象之间的继承,关联,组合.
随着程序的进一步扩展,需要把一组相关的变量传递到不同的函数中,这是一个将变量函数组合成类的好场景.(数据与行为的分离)
存储数据(名词)
数据对象CRUD操作行为使用property
property()函数是python的builtin函数,它是一个粘合剂,将对象“.”操作符和set、get、del方法粘合起来,并且,让下划线的私有变量可以在类外访问。
1
2
3
4
5
6
7
8
9
10
11
12
13class Student(object):
def score(self):
return self._score
def score(self, value):
if not isinstance(value, int):
raise ValueError('score must be an integer!')
if value < 0 or value > 100:
raise ValueError('score must between 0 ~ 100!')
self._score = value
- 参数也是另一种对象类型(自身就是文档)
数据行为操作(动词)
- 为了看起来像函数一样更易用,可以在init构造函数中接收参数而不是在方法中.
管理对象(有点类似之前自己使用main实现的函数,保证步骤顺序)
python不像java语言,类私有变量可以直接访问,所以变量可以直接访问,无需访问方法.
使用property优雅的处理对象属性:可以直接访问name->property构造函数->调用方法,看起来跟直接访问属性一样.
1 | class Color: |
其它
1 | from __future__ import absolute_import |
1 | baseexcept(SystemExit , KeyboardInterrupt , and GeneratorExit (these three derive directly from BaseException instead). |