方法默认参数是不可变对象
1 | def add_end(L=[]): |
正确方法:
1 | def add_end(L=None): |
协程和异步io
deque GIL线程安全的 list不安全
copy:shallow copy 浅拷贝 id不一样。
看起来隔离了,但是如果deque里[2]是一个可变对象list,拷贝的是索引
深拷贝:
1 | import copy |
多线程
global interpreter lock 全局解释器锁,
python线程对应c中的线程
一次只有一个线程在一个cpu上
同一时刻只有一个线程在一个cpu上执行字节码。
无法将多个线程映射到多个cpu上,并发受限同时修改global变量的两个线程会不安全
py2和3不同。
按字节码行数/时间片,!!!!会释放全局解释器锁。io操作也会释放1
2
3def add(a):
a=a+1
return a
1 | >>>dis.dis(add) |
Condition 条件变量
两层锁:底层调用wait释放就能acquire。wait分配放入等待队列的锁,等notify。
实现了__enter__
和__exit__
可以用with语句wait
:
- 获得waitter锁
- 放到Condition的waiters双端队列里
- 会释放Condition的锁
notify
:从waiters队列弹出一个,释放waiter锁
Semaphore控制进入数量
socket
AF_IPX:linux进程间通信
SOCK_DGRAM:UDP
服务端.bind(("0.0.0.0",8888))
而不是127.0.0.1(本机局域网ip访问不到)
客户端直接访问.connect(('127.0.0.1',8888))
并且send("".encode("utf-8"))
send的时候一定要发送byte类型
socket模拟http请求
1 | client = socket.socket(socket.AF_INET,socket.SOCK_STREAM) |
装饰器
- LEGB:
- encloseing函数内部与内嵌函数之间 【闭包】
装饰器与AOP
- reload
1. 函数元数据
1 | def f(): |
2. nonlocal
嵌套的def中。允许修改修改嵌套作用域变量。
把信息和回调函数联系起来:lambda or call
- timeout 是闭包内的一个自由变量,在setTimeout中
timeout = k
会创建本地timeout.nonlocal
声明嵌套作用域下的变量 - 可修改参数的装饰器 为包裹函数添加一个属性函数,修改自由变量
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21from functools import wraps
import time
import logging
def warn(timeout):
def decorator(func):
def wrapper(*args,**kargs):
start = time.time()
res = func(*args,**kargs)
used = time.time() -start
if used >timeout:
msg = '%s:%s>%s' % (func.__name__,used,timeout)
logging.warn(msg)
return res
#作为wrapper的一个属性
def setTimeout(k):
nonlocal timeout
timeout = k
# 可以被调用
wrapper.setTimeout = setTimeout
return wrapper
return decorator
测试:
1 | from random import randint |
py2中没有nonnocal
不能修改变量的引用,将timeout实现成一个可变对象
1 | def warn(timeout): |
hashable
不可哈希的元素有:list、set、dict
可哈希的元素有:int、float、str、tuple
- unhashable type: ‘set’ ,
dicc = {set([1]):222}
set 不能当字典键 用frozenset
1
2
3
4
5 #输出交集
if item&frozenset(['2']):
print item
if item.intersection('2'):
print item
frozenset
不可变 存在hash值 没用add\remove
将集合作为字典的键值
dict.update()
求并
1
2
3
4
5
6a =frozenset([3])
b =frozenset([2])
list=[]
list.append(a|b)
list
Out[12]: [frozenset({2, 3})]s.issuperset(t)
测试是否 t 中的每一个元素都在 s 中Python虚拟机是单线程(GIL)只有I/O密集型才能发挥Py的并发行,计算密集型值需要轮询。
配置utf-8输出环境
reload(sys)
sys.setdefaultencoding(‘utf-8’)
string
splitlines()
按照行(‘\r’, ‘\r\n’, \n’)分隔splitlines(True)
保留换行符
内置函数
1 | row = [p == '+' for p in line.split()[0]]#转换成T,F序列 |
- 返回对象的内存地址。 id(a)==id(b)
- issubclass(AA,A) AA是否是A的子类
- python的=是引用 a=1,a=2 右值是int对象 id(a)改变
数字
'{0:o},{1:x},{2:b}'.format(64,64,64)
八进制、16进制、2进制
enumerate 偏移值(index,value)
for (offset,item) in enumerate('apple'):print(item,offset)
help(enumerate)
模块
import sys
sys.path #模块搜索路径
- roload
copy
python3 copy源码分析
- immutable类型: int,float,complex |string tuple frozen set
mutable:
list,dict,set,byte arry
copy使用各自的copy函数1
2
3
4
5copy.py
d[list] = list.copy
d[dict] = dict.copy
d[set] = set.copy
d[bytearray] = bytearray.copya= (1,2,[3]) tuple中的list可变
a[1]=10
id(a) list的地址空间不变
1 | x= [[1,2,3]] |
.copy(x)
浅
id(x)!=id(y) id(x[0])==id(y[0]).deepcopy(x)
深
id(x[0])==id(y[0])递归调用
生成器
g = (x * x for x in range(10))
- 每次调用next()遇到下一个yield返回
运算符重载
__getattr__
点号运算__getattribute__
属性获取__getitem__
列表解析、元组赋值,map、for循环,索引、分片运算;L[::]分片是L(slice(,,)分片对象)的语法糖,getitem接收了slice对象__get/setslice__
已移除__iter__
迭代环境优先尝试iter
读文件
- 读文件的最佳方式
for line in open()
,readlines将整个文件加载到内存 - while True:line = f.readline()比迭代器的for慢,因为迭代器以C语言速度运行,while循环版本通过py虚拟机运行python字节码
迭代
- for循环开始时,通过iter内置函数从迭代对象获得一个迭代器。返回的对象有next方法。
- 文件对象就是自己的迭代器。有自己的next方法
- iter()启动迭代
注解
内置作用域
- import builtins dir(builtins)
前一半是内置的异常,后一半是内置的函数 - LEGB法则python将最后扫描B模块 所以不需要导入
global
1 | b=0 |
- 在函数和类中对全局变量赋值,必须在该函数或者类中声明该变量为全局变量,否则经过赋值操作后,变量为本地变量。
第二章
- .pyc保存py编译后的字节码(不是二进制码,py特定)
- PVM 虚拟机 py引擎编译得到的代码
- pandas.Series是以时间戳为索引的
- 差分计算series.diff()切片
滞后观察(lag observation)列以及预测观察(forecast observation)
resample 重采样、频率推断、生成固定频率日期范围
matplotlib动画
lambda 匿名函数
返回函数对象
列表解析
map
ord()返回单个字符的ASCII整数编码
map(f,list)
将传入的函数依次作用到序列的每个元素,并把结果作为新的list返回。reduce把一个函数作用在一个序列[x1, x2, x3…]上,这个函数必须接收两个参数,reduce把结果继续和序列的下一个元素做累积计算
reduce(f, [x1, x2, x3, x4]) = f(f(f(x1, x2), x3), x4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21res = list(map(ord,'spam'))
res = [ord(x) for x in 'spam']
#res =[115, 112, 97, 109]
[line.rstrip() for line in open('file').readlines()]
list(map((lambda line:line.rstrip()),open('file')))
#['aaa','bbb']
listoftuple=[('bob',35,'mgr'),('amy',40,'dev')]
list(map(lambda row:row[1]),listoftuple)
#[35,40]
#自己实现map
def mymap(func,*seqs):
res=[]
for args in zip(*seqs):
# *args 参数传递语法 可以收集多个序列
res.append(func(*args))
return res
def mymap(func,*seqs):
return [func(*args) for args in zip(*seqs)]reduce:累积求和:sum(list)string2int
zip
zip是map的一个基本嵌套操作
1 | list[zip([1,2,3],[2,3,4,5])] |
- 列表中是表;元组为行,列是元组中的元素
cmp已经移除
1 | def tester(start): |
用函数属性实现nonlocal??
P440
1 | def tester(start): |
call让类看起来是一个可调用的函数
1 | class tester: |
operator
- b=operator.itemgetter(1) 获取对象的1索引
- b(a) 获取 list a 的1索引
- operator.itemgetter 定义了一个函数,作用到对象上获取值
- 与sorted一起用:sorted(dict,key = lambda x:x.values())按字典的values排序
- 按二维list中子元素的第三项排序 key = lambda student:student[2]/key = operator.itemgetter(2)
- operator.itemgetter(1,2) 第二项和第三项
panda 坑
data = pd.read_csv('.\a.csv', parse_dates=['Month'], index_col='Month',date_parser=dateparse)
- Only booleans, lists, and dictionaries are accepted for the ‘parse_dates’ parameter
parse_dates=['Date']
instead ofparse_dates='Date'